传送门
sb题面误导了我半天。
按位考虑,
对于 \(a[i]\)和\(i\)的一位考虑什么样的\(a[j]\)和\(j\)可以转移过来,发现这一位有一种一定可以一种一定不行,还有两种不确定。
考虑魔改\(01trie\)每一个节点\(4\)个儿子,但是这样\(01trie\)会\(T\)。
发现不确定的两种情况\(a[j]\)和\(j\)这一位的异或值一定。
所以可以把\(01trie\)的\(4\)个儿子按异或值两两合并,每一个儿子维护两种情况的\(dp\)值。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=10000000;
int ch[N][2],mx[N][2],a[N],dp[N];
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
int tot=0;
void add(int x,int y,int w,int dep,int &now){
if(now==0)now=++tot;
if(dep==-1)return;
int bit_x=(x>>dep)&1,bit_y=(y>>dep)&1;
add(x,y,w,dep-1,ch[now][bit_x^bit_y]);
mx[ch[now][bit_x^bit_y]][bit_y]=max(mx[ch[now][bit_x^bit_y]][bit_y],w);
}
int get_max(int x,int y,int dep,int now){
if(now==0)return 0;
if(dep==-1)return 0;
int bit_x=(x>>dep)&1,bit_y=(y>>dep)&1;
if(bit_x==0&&bit_y==1)return max(mx[ch[now][0]][0],get_max(x,y,dep-1,ch[now][1]));
if(bit_x==0&&bit_y==0)return max(mx[ch[now][1]][0],get_max(x,y,dep-1,ch[now][0]));
if(bit_x==1&&bit_y==0)return max(mx[ch[now][0]][1],get_max(x,y,dep-1,ch[now][1]));
if(bit_x==1&&bit_y==1)return max(mx[ch[now][1]][1],get_max(x,y,dep-1,ch[now][0]));
}
int root;
int main(){
int T=read();
while(T--){
int n=read();
for(int i=1;i<=n;i++)a[i]=read();
int ans=0;
root=0;
for(int i=1;i<=n;i++){
dp[i]=max(1,get_max(i-1,a[i],30,root)+1);
add(i-1,a[i],dp[i],30,root);
ans=max(ans,dp[i]);
}
cout<<ans<<endl;
for(int i=0;i<=tot;i++){
mx[i][0]=mx[i][1]=ch[i][0]=ch[i][1]=0;
}
tot=0;
}
return 0;
}
标签:ch,Xor,01trie,int,max,hard,dep,bit,now
From: https://www.cnblogs.com/Xu-daxia/p/16610882.html