1 条题解
-
0
首先考虑前缀和,因为注意到一个数如果被异或两次的话就等于
也就是说:$a_i \oplus a_{i+1} \oplus …… a_j=sum_j \oplus sum_{i-1}$
那我们就变成了对于每一个 找到一个最大的符合要求的 ,这就成了字典树典题了
但是我们要考虑区间的问题,我们每次输入进来一个之后先查询、再插入即可
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #define N 100005 using namespace std; bool Test_MLE_start; int T=1,n,ret=0,tot=1; int a[N],sum[N],wch[21*N],vis[21*N],t[21*N][2],op[30]; struct node{ int l,r,data,len; }ans[N]; inline int reads(){ char c=getchar(); int sum=0,f=1; while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); } while(isdigit(c)){ sum=(sum<<3)+(sum<<1)+(c^'0'); c=getchar(); } return sum*f; } inline void files(){ freopen("E2.in","r",stdin); // freopen("std.out","w",stdout); } inline void clr(){ // Don't forget! } void inserts(int k){ memset(op,0,sizeof(op)); int l=sum[k],p=1; ret=0; while(l){ int p=l%2; l>>=1; op[++ret]=p; } for(int i=21;i>=1;i--){ int ch=op[i]; if(!t[p][ch]) t[p][ch]=++tot; p=t[p][ch]; } wch[p]=sum[k],vis[p]=k; } int asks(int k){ memset(op,0,sizeof(op)); int l=sum[k],p=1; ret=0; while(l){ int p=l%2; l>>=1; op[++ret]=p; } for(int i=21;i>=1;i--){ int ch=op[i],tgt=op[i]^1; if(t[p][tgt]) p=t[p][tgt]; else p=t[p][ch]; } return p; } bool cmp(node a,node b){ if(a.data==b.data){ if(a.r==b.r) return a.len<b.len; return a.r<b.r; } return a.data>b.data; } bool Test_MLE_end; signed main(){ // printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0); // files(); // T=reads(); while(T--){ clr(); n=reads(); for(int i=1;i<=n;i++){ a[i]=reads(); if(i==1) sum[i]=a[i]; else sum[i]=sum[i-1]^a[i]; int now=asks(i),R=vis[now]+1,nUm=wch[now]^sum[i]; // cout<<i<<"->"<<now<<" "<<sum[i]<<"->"<<wch[now]<<"->ans:"; ans[i].data=nUm,ans[i].l=R,ans[i].r=i,ans[i].len=ans[i].r-ans[i].l+1; // cout<<ans[i].data<<" "<<ans[i].l<<" "<<ans[i].r<<" "<<ans[i].len<<"\n"; inserts(i); } sort(ans+1,ans+n+1,cmp); printf("%d %d %d\n",ans[1].data,ans[1].l,ans[1].r); } return 0; }
- 1
信息
- ID
- 184
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- (无)
- 递交数
- 56
- 已通过
- 8
- 上传者