Description

在X星球上有N个国家,每个国家占据着X星球的一座城市。由于国家之间是敌对关系,所以不同国家的两个城市是不会有公路相连的。 
X星球上战乱频发,如果A国打败了B国,那么B国将永远从这个星球消失,而B国的国土也将归A国管辖。A国国王为了加强统治,会在A国和B国之间修建一条公路,即选择原A国的某个城市和B国某个城市,修建一条连接这两座城市的公路。 
同样为了便于统治自己的国家,国家的首都会选在某个使得其他城市到它距离之和最小的城市,这里的距离是指需要经过公路的条数,如果有多个这样的城市,编号最小的将成为首都。 
现在告诉你发生在X星球的战事,需要你处理一些关于国家首都的信息,具体地,有如下3种信息需要处理: 
1、A x y:表示某两个国家发生战乱,战胜国选择了x城市和y城市,在它们之间修建公路(保证其中城市一个在战胜国另一个在战败国)。 
2、Q x:询问当前编号为x的城市所在国家的首都。 
3、Xor:询问当前所有国家首都编号的异或和。

Input

第一行是整数N,M,表示城市数和需要处理的信息数。 
接下来每行是一个信息,格式如题目描述(A、Q、Xor中的某一种)。

Output

输出包含若干行,为处理Q和Xor信息的结果。

Sample Input

10 10
Xor
Q 1
A 10 1
A 1 4
Q 4
Q 10
A 7 6
Xor
Q 7
Xor

Sample Output

11
1
1
1
2
6
2

HINT

对于100%的数据,2<=N<=100000,1<=M<=200000。

LCT维护子树信息(+启发式合并)

这道题也真是强啊,分析了一会码了一会,结果却因为一个傻x错误坑了我一个多小时~

首先,在link时,要把点数少的连接到点数多的上(这其实不应该叫做启发式合并吧)

这样有什么好处?它有两个重要的性质:

1.合并后的重心一定在点数多的树之内,且在连接点到原重心的链上(因为如果在点数少的树之内,重心最后一段的移动路径一定对答案的贡献恒为负,一定不是最优解;而偏移方向不为到连接点方向的话对答案贡献也一定为负)

2.合并后的重心与原重心距离一定不超过点数少的树的点数(假设一个一个插入,偏移距离一定不超过1)

这就可以看出这样做的优势:性质1限定了重心移动的方向,性质2限定了重心移动的距离。

我们考虑:重心发生改变,把它移动的路径分为每次一条边的段,那么每一段对于答案的贡献一定是递减的,直到某一段对答案贡献为负则停止。

那么我们就可以模拟这个过程,将重心设为树根,每次把重心可能的移动路径拿出来,一个一个判断并处理。

嘴上说真简单

实际上,要动态维护子树大小,需要使用LCT维护子树信息。而在LCT中取出重心的移动路径并不是特别容易,需要求出Splay Tree的中序遍历,就要dfs整棵Splay Tree,并在超过范围时停止。

由于重心是固定的,因此将x合并到y上时不能makeroot(y),只能access(y),splay(y)

更复杂的问题是题目不是使用spj,而是强制要求有多个重心时需要选择编号较小的。所以还应该判断编号的影响。

最重要的是,findroot和dfs时都需要pushdown!一开始我在findroot时想起来了,结果到dfs时又忘了,因为这个sb错误zz了一个小时真是气。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define R register int
 4 #define rep(i,a,b) for(R i=a;i<=b;i++)
 5 #define Rep(i,a,b) for(R i=a;i>=b;i--)
 6 #define ms(i,a)    memset(a,i,sizeof(a))
 7 #define gc()       getchar()
 8 #define LL         long long
 9 #define I          inline int
10 #define pa         fa[x]
11 #define lc         ch[x][0]
12 #define rc         ch[x][1]
13 template<class T>void read(T &x){
14     x=0; char c=0;
15     while (!isdigit(c)) c=gc();
16     while (isdigit(c)) x=x*10+(c^48),c=gc();
17 }
18 int const N=100000+3;
19 int const M=200000+3;
20 int n,m,top,st[N],ans,tp,sk[N];
21 int fa[N],ch[N][2],r[N],sum[N],sz[N];
22 I get(int x){return ch[pa][1]==x;}
23 I isr(int x){return ch[pa][0]!=x && ch[pa][1]!=x; }
24 I update(int x){sum[x]=sum[lc]+sum[rc]+sz[x]+1;}
25 I con(int x,int y,int z){fa[x]=y;ch[y][z]=x;}
26 I rotate(int x){
27     int f=fa[x],g=fa[f],c=get(x),cc=get(f);
28     if (!isr(f))  ch[g][cc]=x; fa[x]=g;
29     con(ch[x][c^1],f,c);con(f,x,c^1);
30     update(f); update(x);
31 }
32 I pushd(int x){
33     if(!r[x]) return 0;
34     swap(ch[lc][0],ch[lc][1]);
35     swap(ch[rc][0],ch[rc][1]);
36     r[lc]^=1; r[rc]^=1; r[x]=0;
37 }
38 I splay(int x){
39     top=0; int k=x; while (!isr(k)) st[++top]=k,k=fa[k]; st[++top]=k;
40     while (top) pushd(st[top--]);
41     for(;!isr(x);rotate(x)) if(!isr(pa))  rotate(get(x)==get(pa)? pa :x);
42 }
43 I access(int x){
44     for(int y=0; x;  y=x,x=pa){
45         splay(x);
46         sz[x]+=sum[rc]-sum[y];
47         rc=y,update(x);
48     }
49 }
50 I make(int x){
51     access(x); splay(x); r[x]^=1; swap(lc,rc);
52 }
53 I find(int x){
54     access(x); splay(x);
55     while (lc) x=lc;
56     return x;
57 }
58 I split(int x,int y){
59     make(x); access(y);  splay(y);
60 }
61 I link(int x,int y){
62     make(x);   fa[x]=y; sz[y]+=sum[x]; update(y);
63 }
64 void dfs(int x,int s){
65     if(tp>s) return ;
66     pushd(x);
67     if(lc) dfs(lc,s);
68     sk[++tp]=x;
69     if(rc) dfs(rc,s);
70 }
71 int main(){
72     read(n); read(m);
73     rep(i,1,n) ans^=i,sum[i]=1;
74     while (m--){
75         char s[10];
76         scanf("%s",s);
77         if(s[0]=='X') printf("%d\n",ans);
78         if(s[0]=='A'){
79             int x,y; read(x); read(y);
80             int tx=find(x),ty=find(y);
81             ans^=tx; ans^=ty;
82             splay(tx); splay(ty);
83             if(sum[tx]>sum[ty] || sum[tx]==sum[ty] && x<y)  swap(x,y),swap(tx,ty);
84             int s=sum[tx], ts=sum[tx]+sum[ty];
85             link(x,y);access(x); splay(ty);
86             tp=0,dfs(ty,s); int r=ty;
87             rep(i,1,tp){
88                 splay(sk[i]); int t=sz[sk[i]]+1+sum[ch[sk[i]][1]];
89                 if(2*t>ts || 2*t==ts && r>=sk[i]) r=sk[i];
90             }
91             make(r); ans^=r;
92         }
93         if(s[0]=='Q') {
94             int x; read(x);
95             printf("%d\n",find(x));
96         }
97     }
98 }

View Code

转载于:https://www.cnblogs.com/ZJXXCN/p/10275945.html

bzoj 3510 首都相关推荐

  1. BZOJ 2159 「国家集训队」Crash 的文明世界(第二类斯特林数,换根DP)【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2159 是 hydro 的 BZOJ ...

  2. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  3. S-T平面图中利用最短路求最小割(BZOJ 1001)

    BZOJ 1001: [BeiJing2006]狼抓兔子 最小割 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢 ...

  4. BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)

    题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...

  5. BZOJ 2957楼房重建

    传送门 线段树 //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include< ...

  6. BZOJ 3573 米特运输

    Description 米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储存一直是一个大问题.     D星上有N个城市,我们将其顺序编号为1到N, ...

  7. BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)

    BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...

  8. bzoj 4871: [Shoi2017]摧毁“树状图”

    4871: [Shoi2017]摧毁"树状图" Time Limit: 25 Sec  Memory Limit: 512 MB Submit: 53  Solved: 9 [Su ...

  9. BZOJ 1592. Making the Grade(思维,数据结构优化DP,以及三个拓展问题)[Usaco2008 Feb]【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 BZOJ简单题合集x 目录 BZOJ 1592. Making the Grade 拓展问题一 拓展问 ...

最新文章

  1. 关于站在主管的角度来看企业用人的一些规则
  2. Java线程的两种实现方式
  3. phpcms v9 为分类和内容添加伪静态
  4. oracle如何进入管理器,oracle 启动管理器
  5. Gradle用户指南(章9:Groovy快速入门)
  6. linux系统UDP的socket通信编程
  7. C++中基于范围的for循环
  8. 2019第十届蓝桥杯C/C++ A组省赛 —— 第二题: 数列求值
  9. Webservice初接触
  10. HDU2080 夹角有多大II【数学】
  11. 【linux】ubuntu更改mysql数据文件路径
  12. 如何解决PDF图片字体未嵌入的问题
  13. SQLServer2012服务无法启动Windows不能在本地计算机启动SQLServer(SQLEXPRESS)
  14. OpenGL ES 理解纹理与纹理过滤
  15. 文件上传到ftp服务器命令,ftp上传文件到服务器命令
  16. 如何让单片机I/O口上电复位时为低电平
  17. jquery || 检测已输入字数
  18. ✨❤️CSDN标题党❤️,创意无极限,那不直接全网站都花的飞起?
  19. vivo手机系统android9,vivo终于推送Android9.0,这几款机型你有吗?V粉们已经迫不及...
  20. Macbook Air如何将m4a格式转化为mp3格式?

热门文章

  1. yii2 nginx php配置,nginx下配置Yii2 rewrite、pathinfo等
  2. 电动自行车出口美国认证标准UL2849
  3. 广联达2020写锁工具支持6.0.zip_The Unarchiver for Mac(苹果电脑解压缩工具)
  4. GB33154-2017规范讨论之公共安全视频监控联网信息安全技术要求
  5. 让书和背景分离/去除大区域中小的连通区域(python实现)
  6. 婚姻匹配问题---盖尔-沙普利(Gale-Shapley)稳定匹配算法
  7. kali linux 字体大小,kali linux字体渲染和infinality安装配置
  8. 大鱼吃小鱼 C++ - 栈与非栈
  9. java文件读写long_Java文件的简单读写、随机读写、NIO读写与使用MappedByteBuffer读写...
  10. Ubuntu elasticsearch max virtual memory areas vm.max_map_count [65530] is too low, increase to at le