题目就不贴出来了。
直接上题解:
首先这道题显然要求我们强制在线。
其次我们可以发现一个显然的东西,某个数t对答案的贡献,如果在序列中出现了偶数次,那么贡献为0,否则贡献为本身,那么我们考虑用权值线段树维护每个数出现的次数,然后维护一下答案就可以了。区间答案合并时,判断一下左区间的数的个数即可。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
using namespace std;
const int N=100000+5;
const int M=16385;
const int K=N*40;
int next[N],head[N],to[N],rt[N],a[N],cx[N],cy[N];
int ls[K],rs[K],t[K],s[K];
int tot,cnt;
void R(int &n)
{
int t=0,p=1;char ch;
for(ch=getchar();!('0'<=ch && ch<='9');ch=getchar())
if(ch=='-') p=-1;
for(;'0'<=ch && ch<='9';ch=getchar()) t=t*10+ch-'0';
n=t*p;
}
void add(int x,int y)
{
to[++tot]=y;
next[tot]=head[x];
head[x]=tot;
}
void ch(int x,int &y,int l,int r,int v,int o,int w)
{
if (!(o*x)) y=++cnt;
else y=x;
s[y]=s[x]+w;
if (l==r)
{
if (s[y]&1) t[y]=v;
else t[y]=0;
return;
}
int m=l+r>>1;
if (v<=m)
{
rs[y]=rs[x];
ch(ls[x],ls[y],l,m,v,o,w);
}
else
{
ls[y]=ls[x];
ch(rs[x],rs[y],m+1,r,v,o,w);
}
s[y]=s[ls[y]]+s[rs[y]];
if (s[ls[y]]&1) t[y]=t[ls[y]]-t[rs[y]];
else t[y]=t[ls[y]]+t[rs[y]];
}
void dfs(int x,int y)
{
ch(rt[y],rt[x],0,M,a[x],0,1);
for (int i=head[x];i;i=next[i])
dfs(to[i],x);
}
int main()
{
//freopen("jzoj3878.in","r",stdin);
//freopen("jzoj3878.out","w",stdout);
int n,type,x,q,ans,p;
R(n);R(type);
fo(i,1,n)
{
R(x);R(a[i]);
add(x,i);
}
dfs(1,0);
R(q);
ans=0;
while (q--)
{
R(x);R(p);
fo(i,1,p)
{
R(cx[i]);R(cy[i]);
if (type) cy[i]=((cy[i]^(abs(ans)&16383)));
ch(rt[x],rt[x],0,M,cy[i],1,1);
ch(rt[x],rt[x],0,M,a[cx[i]],1,-1);
}
ans=t[rt[x]];
printf("%d\n",ans);
fo(i,1,p)
{
ch(rt[x],rt[x],0,M,a[cx[i]],1,1);
ch(rt[x],rt[x],0,M,cy[i],1,-1);
}
}
return 0;
}