Codeforces 1720 D, E
作者:互联网
D1
设\(dp(i)\)表示考虑前i个数的最长子序列。枚举\(j\),从\(dp(j)+1\)转移到\(dp(i)\),转移条件就是题中给的那个不等式。
发现\(i-j\)不能超过\(300\),暴力枚举即可。
时间复杂度\(O(300n)\)。
D2
当\(dp(j)\)能转移到\(dp(i)\),当且仅当:\(a_{j}\oplus i<a_{i}\oplus j\)。若这个不等式成立,那么一定是二进制从大往小的前\(k\)位满足\(a_{j}\oplus i=a_{i}\oplus j\),并且第\((k+1)\)位满足\(a_{j}\oplus i=0,a_{i}\oplus j=1\)。
对\(a_{j}\oplus i=a_{i}\oplus j\)可以移项(注意异或的自反律仅用于等式,不能用于不等式,所以对于原式,我们没法移项),可得:\(a_{i}\oplus i=a_{j}\oplus j\)。
那么我们可以将\(a_{i}\oplus i\)作为关键字,放到Trie上。并且记录\(cnt(pos,x,y)\),表示子树\(pos\)中,\(i\)的第\(k\)位为\(x\),\(a_{i}\)的第\(k\)位为\(y\)时的最大DP值。找到最优转移只需枚举我们是哪一位出现不同数位的,设这一位为\(k\),\(i\)第\(k\)位为\(x\),\(a_{i}\)第\(k\)位为\(y\)。由\(a_{j}\oplus i=0,a_{i}\oplus j=1\),可知要满足\(a_{j}\)的第\(k\)位和\(i\)相同,\(a_{i}\)的第\(k\)位和\(j\)不同,也就是\(cnt(pos,y\oplus 1,x)\)。
时间复杂度\(O(n\log A)\),\(A\)为\(a\)的最大取值。
#include<bits/stdc++.h>
#define debug(...) std::cerr<<#__VA_ARGS__<<" : "<<__VA_ARGS__<<std::endl
const int maxn=300005,maxm=300005*32;
int n,ans,a[maxn],f[maxn];
int cur,root,lef[maxm],rig[maxm],cnt[maxm][2][2];
int add() {
++cur; lef[cur]=rig[cur]=0;
memset(cnt[cur],0,sizeof cnt[cur]);
return cur;
}
void insert(int pos,int dig,int key,int id,int dpval) {
if(dig<0) return;
int x=(id&(1<<dig))?1:0,y=(a[id]&(1<<dig))?1:0;
cnt[pos][x][y]=std::max(cnt[pos][x][y],dpval);
if(key&(1<<dig)) {
if(!rig[pos]) rig[pos]=add();
insert(rig[pos],dig-1,key,id,dpval);
} else {
if(!lef[pos]) lef[pos]=add();
insert(lef[pos],dig-1,key,id,dpval);
}
}
int query(int pos,int dig,int key,int id) {
if(dig<0) return 0;
int x=(id&(1<<dig))?1:0,y=(a[id]&(1<<dig))?1:0;
int ret=cnt[pos][y^1][x];
if((key&(1<<dig))&&rig[pos]) ret=std::max(ret,query(rig[pos],dig-1,key,id));
if(!(key&(1<<dig))&&lef[pos]) ret=std::max(ret,query(lef[pos],dig-1,key,id));
return ret;
}
void solve() {
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
cur=ans=0; root=add();
for(int i=0;i<n;i++) {
f[i]=query(root,30,i^a[i],i)+1;
ans=std::max(ans,f[i]);
insert(root,30,i^a[i],i,f[i]);
}
printf("%d\n",ans);
return;
}
int main() {
int T; scanf("%d",&T);
while(T--) solve();
return 0;
}
标签:移项,pos,1720,Codeforces,枚举,oplus,dp,位为 来源: https://www.cnblogs.com/Nastia/p/16609023.html