CF815 D2 Xor-Subsequence (hard version)(01trie)

传送门
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;
} 
posted @ 2022-08-21 21:04  Xu-daxia  阅读(25)  评论(0编辑  收藏  举报