@xiaoziyao
2021-05-04T16:31:19.000000Z
字数 1124
阅读 1222
解题报告
CF*3500的ds题的第一篇题解,好诶!
跑的还挺快,目前cf rk3。
维护大小为的集合,次操作:
神仙ds,类似平衡树的trie高阶操作。
首先考虑只有操作应该怎么维护:操作就直接找到当前结点,交换当前结点的左右儿子然后打上标记,操作就是像在线段树上一样把询问分配到个区间查询。
void getxor(int dep,int now,int val){
if(now==0)
return ;
if((val>>(dep-1))&1)
swp(lc[now],rc[now]);
lazy[now]^=val;
}
int query(int dep,int now,int l,int r,int L,int R){
if(now==0||R<l||r<L)
return 0;
if(L<=l&&r<=R)
return res[now];
int mid=(l+r)>>1;
pushdown(dep,now);
return query(dep-1,lc[now],l,mid,L,R)+query(dep-1,rc[now],mid+1,r,L,R);
}
然后考虑与操作。
由于每次递归找结点太慢,因此可以直接用一个split操作把这些节点“取下来”,然后修改完后再用一个操作“并上去”。
因为最高位为,所以不难发现操作等价于全部取反,一下,然后再次全部取反,由于全部取反等价于异或,所以可以直接用代替。
然后是操作,发现在某一位是等价于对它的左儿子当前这位,然后合并其左儿子至右儿子的,因此我们递归处理就好了,注意如果可以直接用代替的地方需要直接修改。(即需要修改的二进制位与当前子树的没有重复的二进制位)
容易知道每次耗费时间的操作一定会永久删除一个trie树上一个可能的结点,因此时间复杂度为