专栏文章

空之碎物

P14522题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min6dvtu
此快照首次捕获于
2025/12/01 21:18
3 个月前
此快照最后确认于
2025/12/01 21:18
3 个月前
查看原文
超级无敌结论题。与图论无关的两只 log\log 做法。
按位考虑。发现最终的数一个二进制位上一定能被写成 (((x1x2)x3)...)xk(((x_1\ominus x_2)\ominus x_3)\ominus...)\ominus x_k 的形式,而这个东西能取到 11 当且仅当 x1=1x_1=1i[2,k]xi=0\forall i\in[2,k] x_i=0(注意这里的 xkx_k 并不一定是原序列中的某个数的该二进制位,也有可能是若干个数该二进制位下操作的结果)。

Observation 11: xyxx\ominus y\leq x
证明:显然。

Observation 22: 若至少有 22 个数,则取 k=2k=2 一定不劣。
证明:考虑 x1(((x2x3)...)xk)x_1\ominus (((x_2\ominus x_3)\ominus ... )\ominus x_k)。若原来的那个形式能取到 11,则现在这个形式依旧能取到 11

Observation 33: 当 rl+1>26r-l+1>26 时,f(l,r)=maxi=lraif(l,r)=\max_{i=l}^{r} a_i
证明:取 x1=maxi=lraix_1=\max_{i=l}^{r} a_i。则我们需要做的事情就是尽可能让 x1x_1 取值为 11 的那些二进制位保持为 11
构造是容易的,不妨让剩下的数按照 (((x2x3)x4)...)xk(((x_2\ominus x_3)\ominus x_4)\ominus...)\ominus x_k 的形式操作,对于一个二进制位,如果除了 x1x_1 以外剩下的数里面有 2\geq 2 个为 11 的,那么无论如何操作最终这一位一定是 00。所以当剩余数个数 >25>25 时一定存在一种操作方案是的最终与 x1x_1 操作的数为 00。而由于 xyxx\ominus y\leq x,所以我们在 rl+1>26r-l+1>26 时答案一定为区间最大值。

Observation 44: 当 rl+13r-l+1\neq 3 时,f(l,r)f(l,r) 的值一定由 Observation 33 中的构造方式得来(即除去最大值以外的数按某个顺序依次操作,最后最大值操作这个结果)。
上述已经证明 k=2k=2,所以问题转化为 x2x_2x1x_1 的那些为 11 的位尽量为 00
证明:
显然 x1x_1 一定是一个数,不然把其他数丢进 x2x_2 里不劣,同时 x2x_2 一定是按顺序依次操作,因为这样只会让 x2x_2 更小。
如果存在 x1<x1x_1'<x_1x1x2>x1x2x_1'\ominus x_2'>x_1\ominus x_2,那么令 iix1>x1x_1>x_1' 的最高位,jjx1x2>x1x2x_1'\ominus x_2'>x_1\ominus x_2 的最高位。可以得到 i>ji>j,且 x2(i)=1x_2(i)=1。对于所有 i>ii'>ix1(i)=1x_1(i')=1,显然 x1(i)=1x_1'(i')=1。此时其他任何数都无法充当 ii' 位唯一一个 11。所以,对于第 ii 位,其他但凡有一个数为 00 或至少两个数为 11,那么 x2(i)x_2(i) 就一定为 00,这与上述矛盾。
唯一的反例出现在 rl+1=3r-l+1=3,即除了 x1,x1x_1,x_1' 以外的最后一个数该位上为 11 的情况。而且反例很好找,好找到样例 22 就有。

于是剩下的就不难了,从高位到低位贪心,如果这一位 x1x_111 且其他数只有一个 11,把唯一拥有那个 11 的数标记不能充当构成 x2x_2 的第一个数,如果除了它全被标记了那么这一位无论如何取不到 11。对于长度 >26>26 的区间,直接单调栈算出最大值,对于长度 =3=3,暴力枚举所有操作方式即可。
时间复杂度:
  • 长度 =3=3 : O(1)O(1)
  • 长度 >26>26 : O(n)O(n)
  • 长度 {2,4,5,..,26}\in\{2,4,5,..,26\} : O(nlog2V)O(n\log^2 V)nlogVn\log V 个区间,每个区间计算需要 logV\log V
参考代码:
CPP
#include<bits/stdc++.h>
#define int long long
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define _rep(i,a,b) for(int i=(a);i>=(b);i--)
#define subset(i,x) for(int i=(x);i;i=((i-1)&x))
#define pi pair<int,int>
#define arr(a) array<int,(a)>
#define F fflush(stdout)
#define RE return puts("-1"),void()
#define cases(_) while((_)--) solve();
using namespace std;
const int mod=998244353;
inline void ckmin(int& x,int y){x=min(x,y);}
inline void ckmax(int& x,int y){x=max(x,y);}
inline void add(int& x,int y){x=(x%mod+y%mod+mod)%mod;}
inline void mul(int& x,int y){x=(x%mod)*(y%mod)%mod;}
const int N=200005,BIT=25;
int _=1,n,a[N],t[BIT+5],flg[BIT+5],vis[N],ans,res,tmp,nxt[N],pre[N];
inline void add(int x){
	if(x==0) return;
	rep(o,0,BIT) if((a[x]>>o)&1) t[o]++,flg[o]=x;
}
inline int f(int x,int y){
	int res=0;
	rep(o,0,BIT) if((x>>o)&1 && !((y>>o)&1)) res+=(1<<o);
	return res;
}
inline int calc(int x,int y,int z){
	int r1=f(f(x,y),z),r2=f(f(x,z),y),r3=f(f(y,z),x),r4=f(f(y,x),z),r5=f(f(z,y),x),r6=f(f(z,x),y);
	int c1=f(z,f(x,y)),c2=f(y,f(x,z)),c3=f(x,f(y,z)),c4=f(z,f(y,x)),c5=f(x,f(z,y)),c6=f(y,f(z,x));
	int a1=max(max(max(r1,r2),r3),max(max(r4,r5),r6));
	int a2=max(max(max(c1,c2),c3),max(max(c4,c5),c6));
	return max(a1,a2);
}
void solve(){
	scanf("%lld",&n),a[0]=-1;
	rep(i,1,n) scanf("%lld",&a[i]);
	rep(l,1,n){
		int mx=0;
		rep(o,0,BIT) t[o]=0,flg[o]=0;
		rep(r,l,min(l+30,n)){
			if(a[r]<=a[mx]) add(r);
			else add(mx),mx=r;
			rep(o,l,r) vis[o]=0;
			int sum=r-l,res1=0;
			_rep(o,BIT,0) if(t[o]==1 && (a[mx]>>o)&1){
				sum-=(vis[flg[o]]==0);
				if(sum==0) sum++,res1+=(1ll<<o);
				else vis[flg[o]]=1;
			}
			if(r-l!=2) add(ans,a[mx]-res1);
			else add(ans,calc(a[l],a[l+1],a[l+2]));
			add(tmp,a[mx]);
		}
	}
	fill(nxt+1,nxt+n+1,n+1);
	stack<int> st;
	rep(i,1,n){
		while(!st.empty() && a[i]>a[st.top()]) nxt[st.top()]=i,st.pop();
		st.push(i);
	}
	while(!st.empty()) st.pop();
	_rep(i,n,1){
		while(!st.empty() && a[i]>=a[st.top()]) pre[st.top()]=i,st.pop();
		st.push(i);
	}
	rep(i,1,n) add(res,(i-pre[i])*(nxt[i]-i)%mod*a[i]);
	add(ans,res-tmp);
	printf("%lld\n",ans);
}
signed main(){
	cases(_);
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...