博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【uoj207】 共价大爷游长沙
阅读量:4677 次
发布时间:2019-06-09

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

 (题目链接)

题意

  给出一棵无根树,4种操作:在路径集合中加入一条路径,在路径集合中删除一条路径,删一条边加一条边,查询一条边是否被集合中所有路径经过。

Solution

  将路径端点同时异或上一个值,那么如果一条路径被经过,那么它的子树中点的异或和一定等于所有路径的异或和。

  考虑如何用LCT维护这种可加减的子树信息。

  对于询问,我们将询问的点access一下,那么它的所有虚儿子就是它在真实的树中的所有儿子了。

  对于会使轻重边切换的操作:access,link,cut。注意同时更新虚儿子信息。

细节

  link的时候,两端点都要makeroot,否则作为父亲的一点无法更新祖先的信息。

代码

#include
#include
#include
#include
#include
#include
#define LL long long#define inf (1ll<<30)#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)using namespace std; const int maxn=300010;int S,n,m,id,tot,fa[maxn]; struct edge {int u,v,w;}e[maxn];struct node { int son[2],val,sum,rev; //val=x+虚儿子;sum=val+实儿子 int& operator [] (int x) {return son[x];}}tr[maxn]; void reverse(int x) { swap(tr[x][0],tr[x][1]);tr[x].rev^=1;}void pushdown(int x) { if (tr[fa[x]][0]==x || tr[fa[x]][1]==x) pushdown(fa[x]); if (tr[x].rev) { if (tr[x][0]) reverse(tr[x][0]); if (tr[x][1]) reverse(tr[x][1]); tr[x].rev^=1; }}void pushup(int x) { tr[x].sum=tr[tr[x][0]].sum^tr[tr[x][1]].sum^tr[x].val;}void rotate(int x) { int y=fa[x],z=fa[y],l,r; l=tr[y][1]==x;r=l^1; if (tr[z][0]==y || tr[z][1]==y) tr[z][tr[z][1]==y]=x; fa[tr[x][r]]=y;fa[x]=z;fa[y]=x; tr[y][l]=tr[x][r];tr[x][r]=y; pushup(y);pushup(x);}void splay(int x) { pushdown(x); while (tr[fa[x]][0]==x || tr[fa[x]][1]==x) { int y=fa[x],z=fa[y]; if (tr[z][0]==y || tr[z][1]==y) { if ((tr[z][0]==y) ^ (tr[y][0]==x)) rotate(x); else rotate(y); } rotate(x); }}void access(int x) { for (int y=0;x;y=x,x=fa[x]) { splay(x);tr[x].val^=tr[tr[x][1]].sum; tr[x].val^=tr[tr[x][1]=y].sum; pushup(x); }}void makeroot(int x) { access(x);splay(x);reverse(x);}void link(int x,int y) { makeroot(x);makeroot(y); //一定要makeroot(y),否则无法更新y所在的splay上祖先的信息 fa[x]=y;tr[y].val^=tr[x].sum; pushup(y);}void cut(int x,int y) { makeroot(x);access(y);splay(y); fa[x]=tr[y][0]=0;pushup(y);}void modify(int x,int val) { access(x);splay(x); tr[x].val^=val;tr[x].sum^=val;}bool query(int x,int y) { makeroot(x);access(y); //access以后,y在实树上的儿子全为它的虚儿子 return tr[y].val==S ? 1 : 0;} int main() { scanf("%d%d%d",&id,&n,&m); for (int x,y,i=1;i

  

 

转载于:https://www.cnblogs.com/MashiroSky/p/6675292.html

你可能感兴趣的文章
[开发技巧]·pandas如何保存numpy元素
查看>>
冒泡排序
查看>>
我的处女博
查看>>
20171025_Python学习第二周三次课
查看>>
二叉查找树
查看>>
leetcode-17-电话号码的字母组合’
查看>>
Flume 示例
查看>>
Designing for Performance
查看>>
HTML属性的应用
查看>>
HEAP CORRUPTION DETECTED
查看>>
Android项目外接高德地图代码混淆注意事项
查看>>
Android URI简单介绍
查看>>
UVA 1546 - Complete the sequence!(差分法)
查看>>
ubuntu server编译安装nginx
查看>>
实现简单的二级级联
查看>>
Java抓取网页数据(原网页+Javascript返回数据)
查看>>
AjaxPro的使用
查看>>
VS2010的项目配置
查看>>
React native
查看>>
QT-布局管理
查看>>