计蒜客1264:求序列完美度(01字典树)
传送门
题意
略
分析
01字典树,每次插入所有数,按顺序删除查询,按题目要求更新答案即可
学习了一种新的query写法
trick
1.不理解我的code的错误
代码
//wa
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3+10;//集合中的数字个数
int ch[30*maxn][2];//节点的边信息
int num[30*maxn];//记录节点的使用次数,删除时要用
//int val[32*maxn];//节点存储的值
int cnt;//树中节点的个数
int t,n,ans,l,r,z;
int a[1010];
inline void init()
{
cnt=1;mem(ch[0],0);//清空树
}
void insert(int x)//在字典树中插入x,和一般字典树操作相同,将x化成二进制插入到字典树
{
int cur=0;
for(int i=29;i>=0;--i)
{
int idx=((x>>i)&1);
if(!ch[cur][idx])
{
mem(ch[cnt],0);
num[cnt]=0;
ch[cur][idx]=cnt++;
//val[cnt++]=0;
}
//printf("ch[%d][%d]=%d\n",cur,idx,ch[cur][idx]);
cur=ch[cur][idx];
num[cur]++;
}
//val[cur]=x;//最后节点插入val
}
void update(int x)
{
int cur=0;
for(int i=29;i>=0;--i)
{
int idx=((x>>i)&1);
cur=ch[cur][idx];
num[cur]--;
}
}
/*
ll query(ll x)//在字典树(数集)中查找和x异或是最大值的元素y,返回y
{
int cur=0;
for(int i=32;i>=0;--i)
{
int idx=(x>>i)&1;
if(ch[cur][idx^1]) cur=ch[cur][idx^1];else cur=ch[cur][idx];
}
return val[cur];
}
*/
/*
int query(int x)//在字典树(数集)中查找和x异或是最大值的元素y,返回异或的最大值
//带删除操作的查询
{
int cur=0;
for(int i=32;i>=0;--i)
{
int idx=(x>>i)&1;
if(ch[cur][idx^1]&&num[ch[cur][idx^1]]) cur=ch[cur][idx^1];else cur=ch[cur][idx];
}
//printf("val(%d)=%d\n",cur,val[cur]);
return val[cur]^x;
}
*/
int get_ans(int x)
{
int cur=0,ret=0;
for(int i=29;i>=0;--i)
{
int idx=(((x>>i)&1)^1);
if(num[ch[cur][idx]]) cur=ch[cur][idx],ret|=(1<<i);
else cur=ch[cur][idx^1];
}
return ret;
}
void solve(int p)
{
init();
F(i,1,n) insert(a[i]);
int sum=0;
F(i,p,n)
{
update(a[i]);
sum+=a[i];
int ret=get_ans(sum);
if(ret>ans) ans=ret,l=p,r=i,z=sum^ret;
else if(ret==ans)
{
if(p<l) l=p,r=i,z=sum^ret;
else if(p==l&&i<r) r=i,z=sum^ret;
}
}
}
int main()
{
for(scanf("%d",&t);t--;)
{
scanf("%d",&n);
F(i,1,n) scanf("%d",a+i);
ans=-1;
F(i,1,n) solve(i);
printf("%d %d %d %d\n",l,r,z,ans);
}
return 0;
}
//ac
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int n,a[maxn];
struct node
{
int l,r,x,mx;
}ans;
int ch[maxn*30][2],sz,val[maxn*30];
void insert(int x)
{
int u=0;
for(int i=29;i>=0;i--)
{
int c=((x>>i)&1);
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
val[u]++;
}
}
inline void del(int x)
{
int u=0;
for(int i=29;i>=0;i--)
{
int c=((x>>i)&1);
u=ch[u][c];
val[u]--;
}
}
int get_ans(int x)
{
int u=0,tep=0;
for(int i=29;i>=0;i--)
{
int c=(((x>>i)&1)^1);
if(val[ch[u][c]])u=ch[u][c],tep|=(1<<i);
else u=ch[u][c^1];
}
return tep;
}
inline void init()
{
sz=1;memset(ch[0],0,sizeof(ch[0]));
for(int i=1;i<=n;i++)insert(a[i]);
}
inline void solve(int p)
{
init();
int sum=0;
for(int i=p;i<=n;i++)
{
del(a[i]);
sum+=a[i];
int g=get_ans(sum);
if(g>ans.mx)ans.mx=g,ans.l=p,ans.r=i,ans.x=sum^g;
else if(g==ans.mx)
{
if(p<ans.l)ans.l=p,ans.r=i,ans.x=sum^g;
else if(p==ans.l&&i<ans.r)ans.r=i,ans.x=sum^g;
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
ans.mx=-1;
for(int i=1;i<=n;i++)solve(i);
printf("%d %d %d %d\n",ans.l,ans.r,ans.x,ans.mx);
}
return 0;
}
一直地一直地往前走