5分。。。。
T1 LOJ 计算几何瞎暴力
维护以下操作:
1、序列末尾加一个数
2、序列全体从小到大排序
3、查询区间和
4、序列全体异或一个数k
序列全体异或一个数,很明显是trie树
那么序列全体从大到小排序就是把一个个数插入trie树的过程
那么就需要一个数组,存储还没有插入trie树的数
全体异或:
这里需要两个标记:
xortag表示当前序列是异或了什么,
trie树里1个tag 表示trie树是在异或了tag之后有序
为什么需要标记?
假设当前是二进制第i位,如果i&标记的第i位为真,那么查询的时候1相当于0,0相当于1
为什么要两个标记?
因为有可能对全体执行异或操作,这样原来有序的trie树直接异或就无序了。
所以tag用来表示trie树在当前tag下是有序的序列
查询子树和时,用xortag
在判断向左还是向右走时,要用trie树里的tag
因为trie树里的顺序不变
有了标记,查询区间和时,需要维护的就是二进制的每一位1的出现次数
如果&标记的第i为为真,就用0的个数
否则用1的个数
#include<cstdio> #include<iostream> using namespace std; typedef long long LL; #define N 200001 void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } int xortag,bit[31]; struct TRIE { int len,tag,root; int ch[N*31][2],sum[N*31][31],siz[N*31]; TRIE() { len=0; tag=0; root=0; } void insert(int x) { int rt=root,id; for(int i=29;i>=0;--i) { id=(x&bit[i])>0; if(!ch[rt][id]) ch[rt][id]=++len; rt=ch[rt][id]; siz[rt]++; for(int j=0;j<30;++j) if(x&bit[j]) sum[rt][j]++; } } LL getsum(int x) { LL ans=0; for(int i=0;i<30;++i) if(xortag&bit[i]) ans+=1ll*(siz[x]-sum[x][i])*bit[i]; else ans+=1ll*sum[x][i]*bit[i]; return ans; } LL query(int x) { if(!x) return 0; int rt=root,l,r; LL ans=0; for(int i=29;i>=0;--i) { l=0,r=1; if(tag&bit[i]) swap(l,r); if(x<=siz[ch[rt][l]]) rt=ch[rt][l]; else { ans+=getsum(ch[rt][l]); x-=siz[ch[rt][l]]; rt=ch[rt][r]; } } ans+=getsum(rt)/siz[rt]*x; return ans; } int getsiz() { return siz[ch[root][0]]+siz[ch[root][1]]; } }Trie; struct ARRAY { int len; ARRAY() { len=0; } int sum[N][31],a[N]; void insert(int x) { x^=xortag; a[++len]=x; for(int i=29;i>=0;i--) if(x&bit[i]) sum[len][i]=sum[len-1][i]+1; else sum[len][i]=sum[len-1][i]; } void transfer() { Trie.tag=xortag; for(int i=1;i<=len;i++) Trie.insert(a[i]); len=0; } LL query(int x) { LL ans=0; for(int i=0;i<30;++i) if(xortag&bit[i]) ans+=1ll*(x-sum[x][i])*bit[i]; else ans+=1ll*sum[x][i]*bit[i]; return ans; } }Array; LL query(int x) { int siz=Trie.getsiz(); if(x<=siz) return Trie.query(x); else return Trie.query(siz)+Array.query(x-siz); } int main() { freopen("seko.in","r",stdin); freopen("seko.out","w",stdout); bit[0]=1; for(int i=1;i<=30;i++) bit[i]=bit[i-1]<<1; int n,m,x; read(n); for(int i=1;i<=n;++i) read(x),Array.insert(x); read(m); int ty,u,v; while(m--) { read(ty); if(ty==1) { read(v); Array.insert(v); } else if(ty==2) Array.transfer(); else if(ty==3) { read(u);read(v); printf("%I64d\n",query(v)-query(u-1)); } else { read(v); xortag^=v; } } return 0; }