在序列上维护4个操作
1.在序列的尾端添加x
2.输出Al~Ar的和
3.将所有数异或x
4.将序列从小到大排序
第一眼看上去是Splay于是头铁硬刚了一发
后来发现splay没法异或
去百度“维护异或 数据结构”
然后看到了Trie树 学习了一个
1.直接插到序列里
2.考虑前缀和 因为Trie树所管辖的下标区间是有序的,所以这里相当于求Trie树中最小的x个数的,记一下每个点下面数字个数(sz)就可以了
3.考虑整体打一个xortag 对于当前存在的xortag 我们将它的每一位分解到Trie树上跑,如果xortag某一位为1,那么其实相当于该位置的左儿子比右儿子大 处理一下即可
4.把序列插到Trie树里
然后瞎暴力/滑稽
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #include<vector> #include<queue> #include<set> #include<map> #include<stack> #define ll long long #define pi 3.14 #define eps 1e-9 #define INF 2147483233 #define m(a) memset(a,0,sizeof(a)) #define M(a) memset(a,127,sizeof(a)) #define REP(i,m,n) for(int i=1;i<=n;i++) #define DWN(i,n,m) for(int i=n;i>=1;i++) #define lowbit(x) x&(-x) #define POJ(n) while(~scanf("%d",&n) && n) using namespace std; const int maxn=1e5,maxh=30; int xortag,n,m; struct trie { int ch[maxn*maxh][2]; int sz[maxn*maxh]; int sum[maxn*maxh][maxh]; int root=0; int len=0; int tag=0; void insert(int x) { int u=root; for(int i=maxh-1;i>=0;--i) { int id=((x&(1<<i))>0); if(!ch[u][id]) ch[u][id]=++len; u=ch[u][id]; ++sz[u]; for(int j=0;j<maxh;++j) if(x&(1<<j)) sum[u][j]++; } } long long getsum(int x) { long long ans=0; for(int i=0;i<maxh;++i) if(xortag&(1<<i)) ans+=(sz[x]-sum[x][i])*(1LL<<i);else ans+=sum[x][i]*(1LL<<i); return ans; } long long query(int x) { if(x==0) return 0; int u=root; long long ans=0; for(int i=maxh-1;i>=0;--i) { int l=0,r=1; if(tag&(1<<i)) swap(l,r); if(x<=sz[ch[u][l]]) u=ch[u][l]; else { ans+=getsum(ch[u][l]); x-=sz[ch[u][l]]; u=ch[u][r]; } } ans+=getsum(u)/sz[u]*x; return ans; } int getsize() { return sz[ch[root][0]]+sz[ch[root][1]]; } }Trie; struct array { int a[maxn+50]; int sum[maxn+50][maxh]; int len=0; void insert(int x) { x^=xortag; a[++len]=x; for(int i=0;i<maxh;++i) sum[len][i]=sum[len-1][i]+((x&(1<<i))>0); } long long query(int x) { long long ans=0; for(int i=0;i<maxh;++i) if(xortag&(1<<i)) ans+=(x-sum[x][i])*(1LL<<i);else ans+=sum[x][i]*(1LL<<i); return ans; } void transfer() { Trie.tag=xortag; for(int i=1;i<=len;++i) Trie.insert(a[i]); len=0; } }Array; long long query(int x) { if(x<=Trie.getsize()) return Trie.query(x); else return Trie.query(Trie.getsize())+ Array.query(x-Trie.getsize()); } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) { int x; scanf("%d",&x); Array.insert(x); } scanf("%d",&m); for(int i=1;i<=m;++i) { int op,x,y; scanf("%d",&op); if(op==1) { scanf("%d",&x); Array.insert(x); } if(op==2) { scanf("%d%d",&x,&y); printf("%lld\n",query(y)-query(x-1)); } if(op==3) { scanf("%d",&x); xortag^=x; } if(op==4) Array.transfer(); } return 0; }
时间: 2024-11-25 00:36:14