這個題是一個精彩的分析性質區間離散的問題
維護鏈真的一絕。
最短
#include<bits/stdc++.h>
#define maxn 200005
#define lim 30
using namespace std;
int n,q,K,f[lim][maxn];
map<int,int>t1,rt;
int Find(int x){
int r=x%K;x/=K;for(;~r&1;r>>=1);
for(int i=lim-1;i>=0;i--) if(x>>i&1) r=f[i][r];
return r;
}
int sum[maxn*lim],lc[maxn*lim],rc[maxn*lim],cnt;
void Add(int &u,int l,int r,int p,int v){
if(!u)u=++cnt;sum[u] ^= v;
if(l==r) return;
int mid=(l+r)>>1;p<=mid?Add(lc[u],l,mid,p,v):Add(rc[u],mid+1,r,p,v);
}
int Query(int u,int l,int r,int p){
if(!u || l==r) return sum[u];
int mid = (l+r)>>1;
return p<=mid?Query(lc[u],l,mid,p):(sum[lc[u]]^Query(rc[u],mid+1,r,p));
}
int main(){
scanf("%d%d%d",&n,&q,&K);
int t = K , lB = (K&-K)-1;
for(;~t&1;t>>=1);
for(int i=1;i<t;i+=2){
int v=i+t;for(;~v&1;v>>=1);
f[0][i]=v;
}
for(int j=1;j<lim;j++) for(int i=1;i<=t;i+=2) f[j][i] = f[j-1][f[j-1][i]];
for(int op,x,v;q--;){
scanf("%d%d",&op,&x);
for(t=1;x%K==0;x/=K,t*=K);
if(op == 1){
scanf("%d",&v);
for(;x*t<=n && (x&lB);){
t1[x*t] ^= v,x+=x%K;
for(;x%K==0;x/=K,t*=K);
}
if(x*t <= n) Add(rt[t*Find(x)],1,n,x*t,v);
}
else{
int ans = 0;
for(;x;){
if(x&lB) ans ^= t1[x*t];
else ans ^= Query(rt[t*Find(x)],1,n,x*t);
x-=x%K;
for(;x&&x%K==0;x/=K,t*=K);
}
printf("%d\n",ans);
}
}
}