博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Lydsy1805月赛] 对称数
阅读量:5081 次
发布时间:2019-06-12

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

 

    挺不错的一道数据结构题QWQ。

    一开始发现这个题如果不看数据范围的话,妥妥的树上莫队啊23333,然鹅10组数据是不可能让你舒舒服服的树上莫队卡过的23333

    于是想了想,这个题的模型就是,把u到v链上的权值出现奇偶次的01串搞出来,然后第一个0的位置就是所求。。。。。

    但是这个01串并不是很好搞,因为每一位都得异或啊。。。。这样复杂度就要乘上一个 200000/32了(bitset压位),还不如树上莫队呢QWQ

 

    不过有一种套路,叫做hash异或,我们就给每一个权值随机一个unsined long long范围的hash值,大概率保证询问涉及的子集的异或和不为0(这个主要看人品了。。。因为总的来说肯定会有很多子集的异或和为0,但是因为子集总数太过庞大,询问涉及的只是小部分,所以出错概率还是很小的2333)

 

    这样,如果一个区间所有数都出现奇数次,那么区间的hash异或起来就和 路径权值线段树在这个区间异或起来的值一样了,直接在主席树上二分即可。。。

    (注意lca是要被算上的,但是如果直接用到根前缀的两个主席树异或的话lca是会被消去的)

 

#include
#define ll unsigned long longusing namespace std;const int maxn=200005;#define mid (l+r>>1)int T,n,a[maxn],m,to[maxn*2],ne[maxn*2],dep[maxn],le,w,A,B,ans;int hd[maxn],num,siz[maxn],son[maxn],cl[maxn],f[maxn],ri,lca;inline void add(int x,int y){ to[++num]=y,ne[num]=hd[x],hd[x]=num;}ll val[maxn],Xor[maxn],now;struct node{ ll sum; node *lc,*rc;}nil[maxn*37],*rot[maxn],*cnt;inline void init(){ nil->sum=0; nil->lc=nil->rc=rot[0]=cnt=nil; fill(hd+1,hd+n+1,0),num=0; memset(son,0,sizeof(son));}node *update(node *u,int l,int r){ node *ret=++cnt; *ret=*u,ret->sum^=val[le]; if(l==r) return ret; if(le<=mid) ret->lc=update(ret->lc,l,mid); else ret->rc=update(ret->rc,mid+1,r); return ret;}void query(node *u,int l,int r){ if(l>=le&&r<=ri){ now^=u->sum; return;} if(le<=mid) query(u->lc,l,mid); if(ri>mid) query(u->rc,mid+1,r);}void Fdfs(int x,int fa){ f[x]=fa,siz[x]=1,dep[x]=dep[fa]+1; le=a[x],rot[x]=update(rot[fa],1,200001); for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa){ Fdfs(to[i],x),siz[x]+=siz[to[i]]; if(!son[x]||siz[to[i]]>siz[son[x]]) son[x]=to[i]; }}void Sdfs(int x,int tp){ cl[x]=tp; if(!son[x]) return; Sdfs(son[x],tp); for(int i=hd[x];i;i=ne[i]) if(to[i]!=f[x]&&to[i]!=son[x]) Sdfs(to[i],to[i]);}int LCA(int x,int y){ while(cl[x]!=cl[y]){ if(dep[cl[x]]>dep[cl[y]]) x=f[cl[x]]; else y=f[cl[y]]; } return dep[x]
lc->sum^v->lc->sum^((a[lca]>=l&&a[lca]<=mid)?val[a[lca]]:0))==(Xor[mid]^Xor[l-1])) query(u->rc,v->rc,mid+1,r); else query(u->lc,v->lc,l,mid);}inline void solve(){ Fdfs(1,0),Sdfs(1,1); while(m--){ scanf("%d%d",&A,&B),lca=LCA(A,B); query(rot[A],rot[B],1,200001); printf("%d\n",ans); }}int main(){// freopen("data.in","r",stdin);// freopen("data.out","w",stdout); val[1]=1; for(int i=2;i<=200001;i++) val[i]=val[i-1]*233ll; for(int i=1;i<=200001;i++) Xor[i]=val[i]^Xor[i-1]; scanf("%d",&T); while(T--){ init(),scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",a+i); int uu,vv; for(int i=1;i

 

转载于:https://www.cnblogs.com/JYYHH/p/9099254.html

你可能感兴趣的文章
c#自定义控件中的事件处理
查看>>
django Models 常用的字段和参数
查看>>
IOS--沙盒机制
查看>>
使用 JointCode.Shuttle 访问任意 AppDomain 的服务
查看>>
sqlite的坑
查看>>
digitalocean --- How To Install Apache Tomcat 8 on Ubuntu 16.04
查看>>
【题解】[P4178 Tree]
查看>>
Jquery ui widget开发
查看>>
Mongo自动备份
查看>>
cer证书签名验证
查看>>
synchronized
查看>>
【深度学习】caffe 中的一些参数介绍
查看>>
Python-Web框架的本质
查看>>
QML学习笔记之一
查看>>
Window 的引导过程
查看>>
App右上角数字
查看>>
从.NET中委托写法的演变谈开去(上):委托与匿名方法
查看>>
小算法
查看>>
201521123024 《java程序设计》 第12周学习总结
查看>>
新作《ASP.NET MVC 5框架揭秘》正式出版
查看>>