[关闭]
@xiaoziyao 2021-05-04T08:31:19.000000Z 字数 1124 阅读 1033

CF1515H Phoenix and Bits解题报告

解题报告


CF1515H Phoenix and Bits解题报告:

更好的阅读体验

CF*3500的ds题的第一篇题解,好诶!

跑的还挺快,目前cf rk3。

题意

维护大小为的集合次操作:

分析

神仙ds,类似平衡树的trie高阶操作。

首先考虑只有操作应该怎么维护:操作就直接找到当前结点,交换当前结点的左右儿子然后打上标记,操作就是像在线段树上一样把询问分配到个区间查询。

  1. void getxor(int dep,int now,int val){
  2. if(now==0)
  3. return ;
  4. if((val>>(dep-1))&1)
  5. swp(lc[now],rc[now]);
  6. lazy[now]^=val;
  7. }
  8. int query(int dep,int now,int l,int r,int L,int R){
  9. if(now==0||R<l||r<L)
  10. return 0;
  11. if(L<=l&&r<=R)
  12. return res[now];
  13. int mid=(l+r)>>1;
  14. pushdown(dep,now);
  15. return query(dep-1,lc[now],l,mid,L,R)+query(dep-1,rc[now],mid+1,r,L,R);
  16. }

然后考虑操作。

由于每次递归找结点太慢,因此可以直接用一个split操作把这些节点“取下来”,然后修改完后再用一个操作“并上去”。

因为最高位为,所以不难发现操作等价于全部取反,一下,然后再次全部取反,由于全部取反等价于异或,所以可以直接用代替。

然后是操作,发现在某一位是等价于对它的左儿子当前这位,然后合并其左儿子至右儿子的,因此我们递归处理就好了,注意如果可以直接用代替的地方需要直接修改。(即需要修改的二进制位与当前子树的没有重复的二进制位)

容易知道每次耗费时间的操作一定会永久删除一个trie树上一个可能的结点,因此时间复杂度为

AC记录&代码

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注