第一种是可持久化01trie和优先队列的。弹出一个最大值,就分治填入左右段区间。但是10-13,18-21wa。代码如下:
#include <bits/stdc++.h>
using namespace std;
struct node{
long long l,r,o,p,va;//l左边界,r右边界,o当前元素位置,p最大异或值元素位置,va最大异或值
bool operator < (const node &t) const
{
return this->va<t.va;
}
}w,w1,w2;
long long s[500005],g[500005],pass[500005*35],t[500005*35][2],got,tot,pos[500005*35];
priority_queue <node> q;
void insert(long long f,long long id)
{
g[++got]=++tot;
long long x=g[got-1],y=g[got];
for(int i=34;i>=0;i--)
{
int v=(f>>i)&1;
t[y][!v]=t[x][!v];
t[y][v]=++tot;
x=t[x][v];
y=t[y][v];
pass[y]=pass[x]+1;
}
pos[y]=id;
}
long long checkpos(long long x,long long y,long long f)
{
for(int i=34;i>=0;i--)
{
int v=(f>>i)&1;
if(pass[t[y][!v]]>pass[t[x][!v]])
{
x=t[x][!v];
y=t[y][!v];
}
else
{
x=t[x][v];
y=t[y][v];
}
}
return pos[y];
}
int main()
{
int n,k;
cin>>n>>k;
insert(0,1);
n++;
for(int i=2;i<=n;i++)
{
long long a;
cin>>a;
s[i]=s[i-1]^a;
insert(s[i],i);
}
for(int i=1;i<=n;i++)
{
w.l=1;
w.r=n;
w.o=i;
w.p=checkpos(g[0],g[n],s[w.o]);
w.va=s[w.o]^s[w.p];
q.push(w);
}
long long sum=0;
for(int i=1;i<=2*k;i++)
{
w=q.top();
sum+=w.va;
q.pop();
if(w.p>w.l)
{
w1.l=w.l;
w1.r=w.p-1;
w1.o=w.o;
w1.p=checkpos(g[w1.l-1],g[w1.r],s[w1.o]);
w1.va=s[w1.o]^s[w1.p];
q.push(w1);
}
if(w.p<w.r)
{
w2.l=w.p+1;
w2.r=w.r;
w2.o=w.o;
w2.p=checkpos(g[w2.l-1],g[w2.r],s[w2.o]);
w2.va=s[w2.o]^s[w2.p];
q.push(w2);
}
}
sum=sum/2;
cout<<sum;
return 0;
}
这种失败以后我换了个方法,就是查询每个元素的第1大的异或值给优先队列。弹出一个,就塞入k+1大的。但是我的结构体里存元素下标i就全ac,代码如下
#include <bits/stdc++.h>
using namespace std;
struct node{
long long va;//va最大异或值
int o,p;
bool operator < (const node &t) const
{
return this->va<t.va;
}
}w;
long long pass[500005*35],t[500005*35][2],tot,s[500005];
priority_queue <node> q;
void insert(long long x)
{
int u=0;
for(int i=34;i>=0;i--)
{
int v=(x>>i)&1;
if(t[u][v]==0) t[u][v]=++tot;
u=t[u][v];
pass[u]++;
}
}
long long check(long long x,int p)
{
long long u=0,res=0;
for(int i=34;i>=0;i--)
{
int v=(x>>i)&1;
if(pass[t[u][!v]]>=p)
{
res+=(1ll<<i);
u=t[u][!v];
}
else
{
p-=pass[t[u][!v]];
u=t[u][v];
}
}
return res;
}
int main()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>s[i];
s[i]^=s[i-1];
}
for(int i=0;i<=n;i++) insert(s[i]);
for(int i=0;i<=n;i++)
{
w.o=i;
w.p=1;
w.va=check(s[w.o],w.p);
q.push(w);
}
long long sum=0;
for(int i=1;i<=2*k;i++)
{
w=q.top();
sum+=w.va;
q.pop();
w.p++;
w.va=check(s[w.o],w.p);
q.push(w);
}
cout<<sum/2;
return 0;
}
结构体直接存元素的值s[i]就全wa。代码如下
#include <bits/stdc++.h>
using namespace std;
struct node{
long long va;//va最大异或值
int o,p;
bool operator < (const node &t) const
{
return this->va<t.va;
}
}w;
long long pass[500005*35],t[500005*35][2],tot,s[500005];
priority_queue <node> q;
void insert(long long x)
{
int u=0;
for(int i=34;i>=0;i--)
{
int v=(x>>i)&1;
if(t[u][v]==0) t[u][v]=++tot;
u=t[u][v];
pass[u]++;
}
}
long long check(long long x,int p)
{
long long u=0,res=0;
for(int i=34;i>=0;i--)
{
int v=(x>>i)&1;
if(pass[t[u][!v]]>=p)
{
res+=(1ll<<i);
u=t[u][!v];
}
else
{
p-=pass[t[u][!v]];
u=t[u][v];
}
}
return res;
}
int main()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>s[i];
s[i]^=s[i-1];
}
for(int i=0;i<=n;i++) insert(s[i]);
for(int i=0;i<=n;i++)
{
w.o=s[i];
w.p=1;
w.va=check(w.o,w.p);
q.push(w);
}
long long sum=0;
for(int i=1;i<=2*k;i++)
{
w=q.top();
sum+=w.va;
q.pop();
w.p++;
w.va=check(w.o,w.p);
q.push(w);
}
cout<<sum/2;
return 0;
}
目前就是搞不懂第一个代码哪里错了。还有就是第二第三个代码,为什么必须存下标i,不能存s[i]。 回答必关,感谢各位巨佬