博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj3510 首都
阅读量:5155 次
发布时间:2019-06-13

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

题目描述:给你n个点和m个操作:

1.链接两个点。

2.查询某点所在树的重心。

3.查询所有树重心的异或和。

其实就是lct维护虚子树,链接时新重心一定在原来的两重心连线上,相当于splay查询区间第k大值(区间中点)。

代码:

#include
#include
#define N 100050int n,m;int fa[N],rt[N],ch[N][2],s[N],sx[N],sr;bool res[N];bool is_not_root(int x){ return (ch[fa[x]][0]==x)|(ch[fa[x]][1]==x);}void update(int x){ s[x]=s[ch[x][0]]+s[ch[x][1]]+sx[x]+1;}void reser(int x){ res[x]^=1; std::swap(ch[x][0],ch[x][1]);}void pushdown(int x){ if(res[x]) { res[x]=0; reser(ch[x][0]); reser(ch[x][1]); }}void down(int x){ if(is_not_root(x))down(fa[x]); pushdown(x);}void rotate(int x){ int y = fa[x],k = (ch[y][1]==x); if(is_not_root(y))ch[fa[y]][ch[fa[y]][1]==y]=x; fa[x]=fa[y]; ch[y][k]=ch[x][!k],fa[ch[x][!k]]=y; ch[x][!k]=y,fa[y]=x; update(y),update(x);}void splay(int x){ down(x); while(is_not_root(x)) { int y = fa[x],z=fa[y]; if(is_not_root(y)) ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y); rotate(x); }}void access(int x){ int y = 0; while(x) { splay(x); sx[x]+=s[ch[x][1]]; sx[x]-=s[y]; ch[x][1]=y; update(x); y=x,x=fa[x]; }}void mtr(int x){ access(x); splay(x); reser(x);}void split(int x,int y){ mtr(x); access(y); splay(y);}void link(int x,int y){ split(x,y); fa[x]=y; sx[y]+=s[x]; update(y);}int findrt(int x){ if(rt[x]==x)return x; return rt[x]=findrt(rt[x]);}int getfa(int x){ int goal = s[x]>>1,tip = (s[x]&1); int ls = 0,rs = 0,ret = 0x7fffffff,vl,vr; while(x) { pushdown(x); vl = s[ch[x][0]]+ls; vr = s[ch[x][1]]+rs; if(vl<=goal&&vr<=goal) { if(tip){ret=x;break;} else if(ret>x)ret=x; } if(vl>vr) { rs += s[ch[x][1]]+sx[x]+1; x = ch[x][0]; }else { ls += s[ch[x][0]]+sx[x]+1; x = ch[x][1]; } } splay(ret); return ret;}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { s[i]=1; sr^=i; rt[i]=i; } int u,v; char sc[10]; for(int i=1;i<=m;i++) { scanf("%s",sc); if(sc[0]=='X') { printf("%d\n",sr); }else if(sc[0]=='Q') { scanf("%d",&u); printf("%d\n",findrt(u)); }else { scanf("%d%d",&u,&v); link(u,v); u=findrt(u),v=findrt(v); split(u,v);//v=rt int r = getfa(v); sr = sr^u^v^r; rt[u] = rt[v] = rt[r] = r; } } return 0;}

 

转载于:https://www.cnblogs.com/LiGuanlin1124/p/9649796.html

你可能感兴趣的文章
css3 2d转换3d转换以及动画的知识点汇总
查看>>
【Java】使用Eclipse进行远程调试,Linux下开启远程调试
查看>>
js对象属性方法
查看>>
对Vue为什么不支持IE8的解释之一
查看>>
Maven安装配置
查看>>
ORA-10635: Invalid segment or tablespace type
查看>>
计算机改名导致数据库链接的诡异问题
查看>>
Windows 8 操作系统 购买过程
查看>>
软件工程课程-个人编程作业
查看>>
Java8内存模型—永久代(PermGen)和元空间(Metaspace)(转)
查看>>
ObjectiveC基础教程(第2版)
查看>>
centos 引导盘
查看>>
Notes of Daily Scrum Meeting(12.8)
查看>>
Apriori算法
查看>>
onlevelwasloaded的调用时机
查看>>
求出斐波那契数组
查看>>
Vue.js 基础学习之组件通信
查看>>
lr_start_transaction/lr_end_transaction事物组合
查看>>
每天一个Linux命令 - 【chkconfig】
查看>>
△UVA10106 - Product(大数乘法)
查看>>