简要题意
你有两个指针 \(l,r\) 初始时 \(l=1,r=n\)。
你可以操作若干次知道 \(l=r\)。
每次操作你可以选择一个整数 \(k \in [l,r)\),记 \(x=\bigoplus_{i=l}^k a_i,y=\bigoplus_{i=k+1}^r a_i\)。
- 如果 \(x \leq y\),你可以令 \(l=k+1\)。
- 如果 \(x \geq y\),你可以令 \(r=k\)。
现在你需要对于每一个整数 \(i \in [1,n]\),求最后能否使 \(l=r=i\)。
\(n \leq 10000\),\(0 \leq a_i < 2^{60}\)。
做法
我们设 \(f_{x,y}\) 表示是否可以令 \(l=x,r=y\)。
首先我们考虑一个区间 \([x,y]\) 可以到达,那么什么样的区间可以被它转移到。
设 \(q=\bigoplus_{i=l}^r a_i\)。
- 如果 \(q=0\),那么区间 \([x,y]\) 可以转移到 \([x,x],[x,x+1]\dots [x,y-1]\) 和 \([x+1,y],[x+2,y]\dots [y,y]\)。
- 如果 \(q \neq 0\),我们设 \(h=\operatorname{highbit}(q)\)。
- 考虑左端点右移转移到 \([t,y]\),那么必然有 \(\bigoplus_{i=t}^y a_i \operatorname{and} h \neq 0\)。
- 考虑右端点左移转移到 \([x,t]\),那么必然有 \(\bigoplus_{i=x}^t a_i \operatorname{and}h \neq 0\)。
考虑按照区间长度从大到小枚举 \(x,y\),然后看 \(f_{x,y}\) 是否可以被转移到。
首先一个区间 \([l,r]\) 能转移到 \([x,y]\) 首先要有 \(l=x\) 或者 \(r=y\)。
然后就是 \(\operatorname{highbit}(\bigoplus_{i=l}^r a_i) \operatorname{and} (\bigoplus_{i=x}^ya_i) \neq 0\)。
我们记录两个辅助转移的数组 \(L,R\),分别表示用来转移 \(l=x\) 和 \(r=y\) 的情况。
看一个区间 \([x,y]\) 是否可以被转移到只需要看 \(\operatorname{highbit}(\bigoplus_{i=l}^r a_i) \operatorname{and} L_x \neq 0\) 和 \(\operatorname{highbit}(\bigoplus_{i=l}^r a_i) \operatorname{and} R_y \neq 0\) 就行,两者满足其一即可转移。
如果求出了一个区间 \([x,y]\) 可以到达,那么我们只需要令 \(L_x=L_x \operatorname{or} \operatorname{highbit}(\bigoplus_{i=l}^r a_i)\),\(R_y=R_y \operatorname{or} \operatorname{highbit}(\bigoplus_{i=l}^r a_i)\) 即可。
放个代码可能好理解一些。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1e5+5;
const int mod = 200003;
int n;
int c[MAXN], tot;
ll stateL[MAXN], stateR[MAXN];
bool dp[10002][10002];
ll a[MAXN], pre[MAXN];
inline ll rebuild(ll x){
tot=0;
while(x){
c[++tot]=x&1;
x>>=1;
}
while(tot<=60) c[++tot]=0;
reverse(c+1,c+1+tot); x=0;
for(int i=1;i<=tot;++i) x+=(ll)c[i]<<(i-1);
return x;
}
inline ll lowbit(ll x){return x & -x;}
inline void solve(){
cin >> n; ll v;
for(int i=1;i<=n;++i) stateL[i]=stateR[i]=0;
for(int i=1;i<=n;++i) cin >> a[i], a[i]=rebuild(a[i]), pre[i]=pre[i-1]^a[i];
for(int i=1;i<=n;++i) for(int j=i;j<=n;++j) dp[i][j]=0; dp[1][n]=1;
for(int len=n;len>=1;--len){
for(int l=1, r=l+len-1;r<=n;++l, ++r){
v=pre[r]^pre[l-1]; v|=1ll<<61;
dp[l][r]|=((stateL[l]&v)!=0);
dp[l][r]|=((stateR[r]&v)!=0);
if(dp[l][r]) stateL[l]|=lowbit(v), stateR[r]|=lowbit(v);
}
}
for(int i=1;i<=n;++i) putchar('0'+dp[i][i]); putchar(10);
return ;
}
int main(){
int t; cin >> t;
while(t--) solve();
return 0;
}
标签:XOR,int,题解,ll,highbit,Conquer,bigoplus,operatorname,neq
From: https://www.cnblogs.com/OccasionalDreamer/p/18012085