博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【LGP5127】子异和
阅读量:5146 次
发布时间:2019-06-13

本文共 2377 字,大约阅读时间需要 7 分钟。

子异和这个名字,真是思博

显然一个集合的子集异或和为,\(2^{|S|-1}\times A\)\(A\)为集合的或和

于是现在的问题变成了树链异或一个数,求树链或和

显然强行拆位是可以做的,复杂度\(O(n\log n\ \log mod)\),还是\(\rm lct\)于是直接飞了

通过一番玄妙重重的推理,我们发现,整体异或上\(c\),对或和的影响是

\[\cup'=(\cup\&∼c)|(c\&∼\cap)\]

这样我们还需要维护与和

\[\cap'=(\cap\&∼c)|(c\&∼\cup)\]

直接\(\rm lct\)维护即可,注意维护与和的时候记得判断当左右儿子为空时就不要取与了

代码

#include
#define re register#define LL long longconst int mod=1e9+7;const int maxn=2e5+5;#pragma GCC optimize(3)#pragma GCC optimize("-fcse-skip-blocks")inline int read() { char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;}unsigned int v[2][maxn],s[2],tag[maxn];int ch[maxn][2],fa[maxn],sz[maxn],rev[maxn],st[maxn],a[maxn];int xx[maxn],yy[maxn],pw[maxn],n,Q;inline int nrt(int x) {return x==ch[fa[x]][0]||x==ch[fa[x]][1];}inline void pushup(int x) { sz[x]=1+sz[ch[x][0]]+sz[ch[x][1]]; v[1][x]=v[0][x]=a[x]; v[0][x]|=(v[0][ch[x][0]]|v[0][ch[x][1]]); if(ch[x][0]) v[1][x]=(v[1][x]&v[1][ch[x][0]]); if(ch[x][1]) v[1][x]=(v[1][x]&v[1][ch[x][1]]);}inline void calc(int x,unsigned int c) { if(!x) return; a[x]^=c,tag[x]^=c; s[0]=v[0][x],s[1]=v[1][x]; v[0][x]=(s[0]&~c)|(c&~s[1]); v[1][x]=(s[1]&~c)|(c&~s[0]);}inline void pushdown(int x) { if(tag[x]) { calc(ch[x][0],tag[x]),calc(ch[x][1],tag[x]); tag[x]=0; } if(rev[x]) { rev[x]=0,rev[ch[x][0]]^=1;rev[ch[x][1]]^=1; std::swap(ch[ch[x][0]][0],ch[ch[x][0]][1]); std::swap(ch[ch[x][1]][0],ch[ch[x][1]][1]); }}inline void rotate(int x) { int y=fa[x],z=fa[y],k=ch[y][1]==x,w=ch[x][k^1]; if(nrt(y)) ch[z][ch[z][1]==y]=x; ch[x][k^1]=y,ch[y][k]=w; pushup(y),pushup(x);fa[w]=y,fa[y]=x,fa[x]=z;}inline void splay(int x) { int y=x,top=0;st[++top]=x; while(nrt(y)) y=fa[y],st[++top]=y; while(top) pushdown(st[top--]); while(nrt(x)) { int y=fa[x]; if(nrt(y)) rotate((ch[y][1]==x)^(ch[fa[y]][1]==y)?x:y); rotate(x); }}inline void access(int x) { for(re int y=0;x;y=x,x=fa[x]) splay(x),ch[x][1]=y,pushup(x);}inline void mrt(int x) { access(x),splay(x),rev[x]^=1;std::swap(ch[x][0],ch[x][1]);}inline void split(int x,int y) { mrt(x),access(y),splay(y);}inline void link(int x,int y) { mrt(x),fa[x]=y;}int main() { n=read();Q=read(); for(re int i=1;i

转载于:https://www.cnblogs.com/asuldb/p/11477946.html

你可能感兴趣的文章
tmux的简单快捷键
查看>>
Vue_(组件通讯)子组件向父组件传值
查看>>
[Serializable]的应用--注册码的生成,加密和验证
查看>>
Android 官方新手指导教程
查看>>
安装 Express
查看>>
Weka中数据挖掘与机器学习系列之基本概念(三)
查看>>
leetcode-Sort List
查看>>
中文词频统计
查看>>
Postman-----如何导入和导出
查看>>
【Linux】ping命令详解
查看>>
Oracle中包的创建
查看>>
关于PHP会话:session和cookie
查看>>
jQuery on(),live(),trigger()
查看>>
treegrid.bootstrap使用说明
查看>>
[Docker]Docker拉取,上传镜像到Harbor仓库
查看>>
导航,头部,CSS基础
查看>>
[USACO 2017 Feb Gold] Tutorial
查看>>
gzip
查看>>
转负二进制(个人模版)
查看>>
LintCode-Backpack
查看>>