Solution Set - LCT
A[洛谷P3690]维护一个森林,支持询问路径xor和,连边(已连通则忽略),删边(无边则忽略),改变点权。
B[洛谷P3203]\(n\)个装置编号为\(0,...,n-1\),从\(i\)可以一步跳到\(i+k_i\),支持修改\(k_i\),询问从一个点开始几步跳出\(n-1\)。
C[洛谷P2486]给定一棵树,点有颜色,支持路径覆盖,询问路径颜色段数。
D[洛谷P4332]给定一棵树,前\(n\)个点各有三个儿子,叶子结点有权\(0/1\),分支结点的权是其三个儿子权值中较多的一个。支持修改叶子结点权值,询问根节点权值。
E[洛谷P2147]维护一个森林,支持连边,删边,询问连通性。
F[洛谷P2542]维护一个图,支持删边,询问两点间必须边数目。
G[洛谷P4234]求给定无向图的最小差值生成树。(最大权与最小权之差)
H[洛谷P4172]维护一个图,支持删边,询问两点间路径最大权的最小值。
I[洛谷P4180]求给定无向图的严格次小生成树。
J[洛谷P4219]维护一个森林,支持加边,询问经过某条边的简单路径数目。
K[洛谷P4299]维护一个森林,支持加边,询问某棵子树重心编号,询问所有子树重心编号的xor和。
LCT:解决动态树问题的一种数据结构。思想是对树做虚实链剖分(每个点随便选一个实儿子),用Splay维护每条实链。由于Splay的灵活性,可以方便地改变虚边和实边。LCT的核心操作包括:①将一个点到根的路径打通为实链(access
);②将一个点设为根(makeroot
)。由此可以实现提取路径(split(x,y)=makeroot(x),access(y)
),连边(link(x,y)=makeroot(x),fa[x]=y
),删边(cut(x,y)=split(x,y),ch[y][0]=fa[x]=0
),查找根(findroot
)。
A模板。
B连边\(i \to \min(i+k_i,n)\),修改时删边,加边,询问时split(i,n)
。
C和Splay专题中打标记的思想是类似的。push_up也很好写。
D把儿子中\(1\)的数量看做关键码。将\(0\)改成\(1\)就修改它向上关键码为\(1\)的点,将\(1\)改成\(0\)就修改它向上关键码为\(2\)的点。那么只用实现区间加,维护最深的\(1\),\(2\)。
E模板。
F用LCT维护边双。注意只用删边,可以倒过来考虑加边。然后用并查集维护边双。两点间第一次连通就在LCT上正常加边,第二次就合并相应的并查集,并遍历整条路径。
LCT维护边权时,可以考虑拆边。
G按边权排序,从小到大枚举最大边,加入最大边时删去其两端点路径上的最小边,并维护选入的最小边权。
H维护瓶颈生成树。也是倒着加边,加入某条边时尝试替换最大边。
I先求最小生成树,然后尝试加入每条边,取出该链上的最小值或次小值更新答案。如果用LCT写,不用删边,只要询问两点间最小边权和次小边权。
LCT维护子树信息时,采用的思想类似于动态DP,即维护所有虚儿子的信息之和。只用在access
和link
中更新。注意link
中要写成makeroot(x),makeroot(y)
,否则会WA。
J模板。询问时可以考虑先删去,然后统计答案,再连回去。
K注意到合并两棵树时,新重心一定在原来的两个重心间的路径上。那么可以提出该路径,在它的Splay上做二分。
点击查看A题代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=3e5+5;
int n,m;map<pii,bool> M;
int fa[N],ch[N][2],val[N],sum[N],tag[N];
#define ls ch[p][0]
#define rs ch[p][1]
void push_up(int p){sum[p]=sum[ls]^sum[rs]^val[p];}
void pushr(int p){tag[p]^=1;swap(ls,rs);}
void push_down(int p){if(tag[p]){tag[p]=0;if(ls)pushr(ls);if(rs)pushr(rs);}}
bool get(int p){return p==ch[fa[p]][1];}
bool isRoot(int p){return ch[fa[p]][0]!=p&&ch[fa[p]][1]!=p;}
void update(int p){if(!isRoot(p))update(fa[p]);push_down(p);}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
if(!isRoot(y))ch[z][y==ch[z][1]]=x;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;
push_up(y);push_up(x);
}
void splay(int x){
update(x);
for(int p=fa[x];!isRoot(x);p=fa[x]){
if(!isRoot(p))rotate(get(p)==get(x)?p:x);
rotate(x);
}
}
void Access(int x){
for(int y=0;x;y=x,x=fa[x])
splay(x),ch[x][1]=y,push_up(x);
}
int findRoot(int p){
Access(p);splay(p);
while(ls)push_down(p),p=ls;
splay(p);return p;
}
void makeRoot(int p){Access(p);splay(p);pushr(p);}
void split(int x,int y){makeRoot(x);Access(y);splay(y);}
bool link(int x,int y){
makeRoot(x);
if(findRoot(y)==x)return false;
fa[x]=y;return true;
}
void cut(int x,int y){split(x,y);ch[y][0]=fa[x]=0;push_up(y);}
#undef ls
#undef rs
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",val+i);
for(int op,x,y;m--;){
scanf("%d%d%d",&op,&x,&y);
if(op==0)split(x,y),printf("%d\n",sum[y]);
if(op==1)if(link(x,y))M[pii(x,y)]=M[pii(y,x)]=1;
if(op==2)if(M[pii(x,y)])cut(x,y),M[pii(x,y)]=M[pii(y,x)]=0;
if(op==3)splay(x),val[x]=y;
}
return 0;
}
点击查看B题代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,m,a[N];
int fa[N],ch[N][2],sum[N],tag[N];
#define ls ch[p][0]
#define rs ch[p][1]
void push_up(int p){sum[p]=sum[ls]+sum[rs]+1;}
void pushr(int p){tag[p]^=1;swap(ls,rs);}
void push_down(int p){if(tag[p]){tag[p]=0;if(ls)pushr(ls);if(rs)pushr(rs);}}
bool get(int p){return p==ch[fa[p]][1];}
bool isroot(int p){return p!=ch[fa[p]][0]&&p!=ch[fa[p]][1];}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
if(!isroot(y))ch[z][y==ch[z][1]]=x;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;push_up(y);push_up(x);
}
void update(int p){if(!isroot(p))update(fa[p]);push_down(p);}
void splay(int x){
update(x);
for(int y=fa[x];!isroot(x);y=fa[x]){
if(!isroot(y))rotate(get(y)==get(x)?y:x);
rotate(x);
}
}
void access(int x){for(int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y,push_up(x);}
void makeroot(int p){access(p);splay(p);pushr(p);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void link(int x,int y){makeroot(x);fa[x]=y;}
void cut(int x,int y){split(x,y);ch[y][0]=fa[x]=0;push_up(y);}
#undef ls
#undef rs
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
link(i,min(n+1,i+a[i]));
}
scanf("%d",&m);
for(int i=1,op,x;i<=m;i++){
scanf("%d%d",&op,&x);++x;
if(op==1)split(x,n+1),printf("%d\n",sum[n+1]-1);
else cut(x,min(n+1,x+a[x])),scanf("%d",a+x),link(x,min(n+1,x+a[x]));
}
return 0;
}
点击查看C题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;char op[3];
int fa[N],ch[N][2],tag[N][2],col[N],lc[N],rc[N],sum[N];
#define ls ch[p][0]
#define rs ch[p][1]
void push_up(int p){
if(ls)lc[p]=lc[ls];else lc[p]=col[p];
if(rs)rc[p]=rc[rs];else rc[p]=col[p];
sum[p]=sum[ls]+sum[rs]+1-(col[p]==rc[ls])-(col[p]==lc[rs]);
}
void make_tag(int p,int op){
if(op==0)tag[p][0]^=1,swap(ls,rs),swap(lc[p],rc[p]);
else tag[p][1]=lc[p]=rc[p]=col[p]=op,sum[p]=1;
}
void push_down(int p){
if(tag[p][0]){tag[p][0]=0;if(ls)make_tag(ls,0);if(rs)make_tag(rs,0);}
if(tag[p][1]){
int v=tag[p][1];tag[p][1]=0;
if(ls)make_tag(ls,v);if(rs)make_tag(rs,v);
}
}
bool get(int p){return p==ch[fa[p]][1];}
bool isroot(int p){return p!=ch[fa[p]][0]&&p!=ch[fa[p]][1];}
void update(int p){if(!isroot(p))update(fa[p]);push_down(p);}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
if(!isroot(y))ch[z][y==ch[z][1]]=x;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;push_up(y);push_up(x);
}
void splay(int x){
update(x);
for(int y=fa[x];!isroot(x);y=fa[x]){
if(!isroot(y))rotate(get(y)==get(x)?y:x);
rotate(x);
}
}
void access(int x){for(int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y,push_up(x);}
void makeroot(int p){access(p);splay(p);make_tag(p,0);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void link(int x,int y){makeroot(x);fa[x]=y;}
#undef ls
#undef rs
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",col+i);
for(int i=1,u,v;i<n;i++)scanf("%d%d",&u,&v),link(u,v);
for(int i=1,u,v,w;i<=m;i++){
scanf("%s",op);
if(op[0]=='C')scanf("%d%d%d",&u,&v,&w),split(u,v),make_tag(v,w);
else scanf("%d%d",&u,&v),split(u,v),printf("%d\n",sum[v]);
}
return 0;
}
点击查看D题代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int n,m,ans;
int fa[N*3],ch[N][2],val[N*3],n1[N],n2[N],tag[N];
#define ls ch[p][0]
#define rs ch[p][1]
void push_up(int p){
if(n1[rs])n1[p]=n1[rs];else if(val[p]!=1)n1[p]=p;else n1[p]=n1[ls];
if(n2[rs])n2[p]=n2[rs];else if(val[p]!=2)n2[p]=p;else n2[p]=n2[ls];
}
void make_tag(int p,int op){tag[p]+=op;val[p]^=3;swap(n1[p],n2[p]);}
void push_down(int p){
if(tag[p]){
if(ls)make_tag(ls,tag[p]);
if(rs)make_tag(rs,tag[p]);
tag[p]=0;
}
}
bool get(int p){return p==ch[fa[p]][1];}
bool isroot(int p){return p!=ch[fa[p]][0]&&p!=ch[fa[p]][1];}
void update(int p){if(!isroot(p))update(fa[p]);push_down(p);}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
if(!isroot(y))ch[z][y==ch[z][1]]=x;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;push_up(y);push_up(x);
}
void splay(int x){
update(x);
for(int y=fa[x];!isroot(x);y=fa[x]){
if(!isroot(y))rotate(get(x)==get(y)?y:x);
rotate(x);
}
}
void access(int x){for(int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y,push_up(x);}
int head[N*3],nxt[N*3],ver[N*3],tot;
void add(int u,int v){ver[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
void dfs(int u){
for(int i=head[u],v;i;i=nxt[i])
dfs(v=ver[i]),val[u]+=val[v]/2;
}
int main(){
scanf("%d",&n);
for(int u=1,v1,v2,v3;u<=n;u++){
scanf("%d%d%d",&v1,&v2,&v3);
add(u,v1);add(u,v2);add(u,v3);
fa[v1]=fa[v2]=fa[v3]=u;
}
for(int i=n+1,x;i<=3*n+1;i++)scanf("%d",&x),val[i]=2*x;
dfs(1);ans=val[1]/2;
scanf("%d",&m);
for(int i=1,p;i<=m;i++){
scanf("%d",&p);
if(val[p]==0){
val[p]=2;access(p=fa[p]);splay(p);
if(!n1[p]){make_tag(p,1);ans^=1;}
else{splay(p=n1[p]);make_tag(rs,1);++val[p];push_up(p);}
}
else{
val[p]=0;access(p=fa[p]);splay(p);
if(!n2[p]){make_tag(p,-1);ans^=1;}
else{splay(p=n2[p]);make_tag(rs,-1);--val[p];push_up(p);}
}
printf("%d\n",ans);
}
return 0;
}
点击查看E题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;char op[15];
int fa[N],ch[N][2],tag[N];
#define ls ch[p][0]
#define rs ch[p][1]
void make_tag(int p){tag[p]^=1;swap(ls,rs);}
void push_down(int p){if(tag[p]){tag[p]=0;if(ls)make_tag(ls);if(rs)make_tag(rs);}}
bool get(int p){return p==ch[fa[p]][1];}
bool isroot(int p){return p!=ch[fa[p]][0]&&p!=ch[fa[p]][1];}
void update(int p){if(!isroot(p))update(fa[p]);push_down(p);}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
if(!isroot(y))ch[z][y==ch[z][1]]=x;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;
}
void splay(int x){
update(x);
for(int y=fa[x];!isroot(x);y=fa[x]){
if(!isroot(y))rotate(get(y)==get(x)?y:x);
rotate(x);
}
}
void access(int x){for(int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y;}
int findroot(int p){
access(p);splay(p);
while(ls)push_down(p),p=ls;
splay(p);return p;
}
void makeroot(int p){access(p);splay(p);make_tag(p);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void link(int x,int y){makeroot(x);fa[x]=y;}
void cut(int x,int y){split(x,y);ch[y][0]=fa[x]=0;}
bool check(int x,int y){makeroot(x);return findroot(y)==x;}
int main(){
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++){
scanf("%s",op);
scanf("%d%d",&u,&v);
if(op[0]=='C')link(u,v);
if(op[0]=='D')cut(u,v);
if(op[0]=='Q')printf(check(u,v)?"Yes\n":"No\n");
}
return 0;
}
点击查看F题代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=1e5+5;
int n,m,k,q[N][3];map<pii,int> M;stack<int> ans;
struct Disjoint_Set{
int fa[N];
void init(int n){for(int i=1;i<=n;i++)fa[i]=i;}
int find(int x){return x==fa[x]?x:(fa[x]=find(fa[x]));}
void Union(int x,int y){x=find(x);y=find(y);if(x!=y)fa[x]=y;}
}S;
int fa[N],ch[N][2],tag[N],sum[N];
#define ls ch[p][0]
#define rs ch[p][1]
#define ref S.find(fa[p])
void push_up(int p){sum[p]=sum[ls]+sum[rs]+1;}
void make_tag(int p){if(!p)return;tag[p]^=1;swap(ls,rs);}
void push_down(int p){if(tag[p]){tag[p]=0;make_tag(ls);make_tag(rs);}}
bool get(int p){return p==ch[ref][1];}
bool isroot(int p){return p!=ch[ref][0]&&p!=ch[ref][1];}
void update(int p){if(!isroot(p))update(ref);push_down(p);}
void rotate(int x){
x=S.find(x);
int y=S.find(fa[x]),z=S.find(fa[y]),op=get(x)^1;
if(!isroot(y))ch[z][get(y)]=x;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;push_up(y);push_up(x);
}
void splay(int p){
update(p);
for(int x=ref;!isroot(p);x=ref){
if(!isroot(x))rotate(get(x)==get(p)?x:p);
rotate(p);
}
}
void access(int p){for(int x=0;p;x=p,p=ref)splay(p),ch[p][1]=x,push_up(p);}
int findroot(int p){
p=S.find(p);access(p);splay(p);
while(ls)push_down(p),p=ls;
splay(p);return p;
}
void makeroot(int p){p=S.find(p);access(p);splay(p);make_tag(p);}
void dfs(int p,int q){
push_down(p);S.Union(p,q);
if(ch[p][0])dfs(ch[p][0],q);
if(ch[p][1])dfs(ch[p][1],q);
}
void link(int x,int y){
x=S.find(x);y=S.find(y);makeroot(x);
if(findroot(y)!=x){fa[x]=y;return;}
dfs(x,x);
}
void split(int x,int y){makeroot(x);access(y);splay(y);}
int query(int x,int y){x=S.find(x);y=S.find(y);split(x,y);return sum[y];}
#undef ls
#undef rs
int main(){
scanf("%d%d",&n,&m);S.init(n);
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);
if(u>v)swap(u,v);
M[pii(u,v)]=1;
}
for(k=1;scanf("%d",&q[k][0]),q[k][0]!=-1;k++){
scanf("%d%d",&q[k][1],&q[k][2]);
if(q[k][1]>q[k][2])swap(q[k][1],q[k][2]);
if(q[k][0]==0)M[pii(q[k][1],q[k][2])]=0;
}--k;
for(auto x:M)if(x.second)link(x.first.first,x.first.second);
for(int i=k;i>=1;i--){
if(q[i][0]==0)link(q[i][1],q[i][2]);
else ans.push(query(q[i][1],q[i][2])-1);
}
while(!ans.empty())printf("%d\n",ans.top()),ans.pop();
return 0;
}
点击查看G题代码
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
int n,m,cnt,ans=1e9,vis[N],l;
struct edge{int u,v,w;}e[N];
bool operator <(const edge&a,const edge&b){return a.w<b.w;}
int fa[N],ch[N][2],tag[N],mn[N],val[N];
#define ls ch[p][0]
#define rs ch[p][1]
void push_up(int p){mn[p]=min(min(mn[ls],mn[rs]),val[p]);}
void make_tag(int p){if(!p)return;tag[p]^=1;swap(ls,rs);}
void push_down(int p){if(tag[p]){tag[p]=0;make_tag(ls);make_tag(rs);}}
bool get(int p){return p==ch[fa[p]][1];}
bool isroot(int p){return p!=ch[fa[p]][0]&&p!=ch[fa[p]][1];}
void update(int p){if(!isroot(p))update(fa[p]);push_down(p);}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
if(!isroot(y))ch[z][get(y)]=x;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;push_up(y);push_up(x);
}
void splay(int x){
update(x);
for(int y=fa[x];!isroot(x);y=fa[x]){
if(!isroot(y))rotate(get(y)==get(x)?y:x);
rotate(x);
}
}
void access(int x){for(int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y,push_up(x);}
int findroot(int p){access(p);splay(p);while(ls)push_down(p),p=ls;splay(p);return p;}
void makeroot(int x){access(x);splay(x);make_tag(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);ch[y][0]=fa[x]=0;push_up(y);}
void link(int x,int y){makeroot(x);fa[x]=y;}
#undef ls
#undef rs
int main(){
memset(mn,0x3f,sizeof(mn));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w),val[i]=i;
for(int i=m+1;i<=m+n;i++)val[i]=1e9;
sort(e+1,e+m+1);
for(int i=1;i<=m;i++){
if(e[i].u==e[i].v)continue;
++cnt;vis[i]=1;int x=e[i].u+m,y=e[i].v+m;
if(findroot(x)==findroot(y)){
--cnt;split(x,y);int t=mn[y];
cut(e[t].u+m,t);cut(e[t].v+m,t);vis[t]=0;
}
link(x,i);link(y,i);
while(!vis[l]&&l<=m)++l;
if(cnt==n-1)ans=min(ans,e[i].w-e[l].w);
}
printf("%d\n",ans);
return 0;
}
点击查看H题代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=2e5+5;
int n,m,k,vis[N];map<pii,int> M;stack<int> ans;
struct edge{int u,v,w;}e[N],q[N];
bool operator <(const edge&a,const edge&b){return a.w<b.w;}
int fa[N],ch[N][2],tag[N],val[N],mx[N];
#define ls ch[p][0]
#define rs ch[p][1]
void push_up(int p){mx[p]=max(max(mx[ls],mx[rs]),val[p]);}
void make_tag(int p){if(!p)return;tag[p]^=1;swap(ls,rs);}
void push_down(int p){if(tag[p]){tag[p]=0;make_tag(ls);make_tag(rs);}}
bool get(int p){return p==ch[fa[p]][1];}
bool isroot(int p){return p!=ch[fa[p]][0]&&p!=ch[fa[p]][1];}
void update(int p){if(!isroot(p))update(fa[p]);push_down(p);}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
if(!isroot(y))ch[z][get(y)]=x;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;push_up(y);push_up(x);
}
void splay(int x){
update(x);
for(int y=fa[x];!isroot(x);y=fa[x]){
if(!isroot(y))rotate(get(y)==get(x)?y:x);
rotate(x);
}
}
void access(int x){for(int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y,push_up(x);}
int findroot(int p){access(p);splay(p);while(ls)push_down(p),p=ls;splay(p);return p;}
void makeroot(int x){access(x);splay(x);make_tag(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);ch[y][0]=fa[x]=0;push_up(y);}
void link(int x,int y){makeroot(x);fa[x]=y;}
#undef ls
#undef rs
void link(int s){
int x=e[s].u+m,y=e[s].v+m;
if(findroot(x)==findroot(y)){
split(x,y);int t=mx[y];
if(e[t].w<=e[s].w)return;
cut(e[t].u+m,t);cut(e[t].v+m,t);
}
link(x,s);link(y,s);
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
if(e[i].u>e[i].v)swap(e[i].u,e[i].v);
}
sort(e+1,e+m+1);
for(int i=1;i<=m;i++)
M[pii(e[i].u,e[i].v)]=i,val[i]=i;
for(int i=1;i<=k;i++){
scanf("%d%d%d",&q[i].w,&q[i].u,&q[i].v);
if(q[i].u>q[i].v)swap(q[i].u,q[i].v);
if(q[i].w==2)vis[M[pii(q[i].u,q[i].v)]]=1;
}
for(int i=1;i<=m;i++)if(!vis[i])link(i);
for(int i=k;i>=1;i--){
if(q[i].w==2)link(M[pii(q[i].u,q[i].v)]);
else{
split(q[i].u+m,q[i].v+m);
ans.push(e[mx[q[i].v+m]].w);
}
}
while(!ans.empty())printf("%d\n",ans.top()),ans.pop();
return 0;
}
点击查看I题代码
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5,INF=1<<30;
int n,m,vis[N],res=INF,cnt;long long ans;
struct edge{int u,v,w;}e[N];
bool operator <(const edge&a,const edge&b){return a.w<b.w;}
int fa[N],ch[N][2],tag[N],val[N],mx[N][2];
#define ls ch[x][0]
#define rs ch[x][1]
void push_up(int x){
mx[x][0]=max(max(mx[ls][0],mx[rs][0]),val[x]);mx[x][1]=-INF;
if(mx[ls][0]<mx[x][0])mx[x][1]=max(mx[x][1],mx[ls][0]);
else mx[x][1]=max(mx[x][1],mx[ls][1]);
if(mx[rs][0]<mx[x][0])mx[x][1]=max(mx[x][1],mx[rs][0]);
else mx[x][1]=max(mx[x][1],mx[rs][1]);
if(val[x]<mx[x][0])mx[x][1]=max(mx[x][1],val[x]);
}
void make_tag(int x){if(!x)return;tag[x]^=1;swap(ls,rs);}
void push_down(int x){if(tag[x]){tag[x]=0;make_tag(ls);make_tag(rs);}}
bool get(int x){return x==ch[fa[x]][1];}
bool isroot(int x){return x!=ch[fa[x]][0]&&x!=ch[fa[x]][1];}
void update(int x){if(!isroot(x))update(fa[x]);push_down(x);}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
if(!isroot(y))ch[z][get(y)]=x;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;push_up(y);push_up(x);
}
void splay(int x){
update(x);
for(int y=fa[x];!isroot(x);y=fa[x]){
if(!isroot(y))rotate(get(y)==get(x)?y:x);
rotate(x);
}
}
void access(int x){for(int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y,push_up(x);}
int findroot(int x){access(x);splay(x);while(ls)push_down(x),x=ls;splay(x);return x;}
void makeroot(int x){access(x);splay(x);make_tag(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void link(int x,int y){makeroot(x);fa[x]=y;}
#undef ls
#undef rs
void link(int s){
int x=e[s].u+m,y=e[s].v+m;
if(findroot(x)==findroot(y))return;
ans+=e[s].w;vis[s]=1;++cnt;link(x,s);link(y,s);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
sort(e+1,e+m+1);
for(int i=1;i<=m&&cnt<n-1;i++){val[i]=e[i].w;if(e[i].u!=e[i].v)link(i);}
for(int i=1;i<=m;i++)if(!vis[i]&&e[i].u!=e[i].v){
int u=e[i].u+m,v=e[i].v+m;split(u,v);
if(mx[v][0]==e[i].w)res=min(res,e[i].w-mx[v][1]);
else res=min(res,e[i].w-mx[v][0]);
}
printf("%lld\n",res+ans);
return 0;
}
点击查看J题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;char op[3];
int fa[N],ch[N][2],tag[N],siz[N],siz2[N];
#define ls ch[x][0]
#define rs ch[x][1]
void push_up(int x){siz[x]=siz[ls]+siz[rs]+1+siz2[x];}
void make_tag(int x){if(!x)return;tag[x]^=1;swap(ls,rs);}
void push_down(int x){if(tag[x]){tag[x]=0;make_tag(ls);make_tag(rs);}}
bool get(int x){return x==ch[fa[x]][1];}
bool isroot(int x){return x!=ch[fa[x]][0]&&x!=ch[fa[x]][1];}
void update(int x){if(!isroot(x))update(fa[x]);push_down(x);}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
if(!isroot(y))ch[z][get(y)]=x;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;push_up(y);push_up(x);
}
void splay(int x){
update(x);
for(int y=fa[x];!isroot(x);y=fa[x]){
if(!isroot(y))rotate(get(y)==get(x)?y:x);
rotate(x);
}
}
void access(int x){
for(int y=0;x;y=x,x=fa[x]){
splay(x);siz2[x]+=siz[ch[x][1]]-siz[y];
ch[x][1]=y;push_up(x);
}
}
int findroot(int x){access(x);splay(x);while(ls)push_down(x),x=ls;splay(x);return x;}
void makeroot(int x){access(x);splay(x);make_tag(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);ch[y][0]=fa[x]=0;push_up(y);}
void link(int x,int y){makeroot(x);makeroot(y);fa[x]=y;siz2[y]+=siz[x];}
#undef ls
#undef rs
int main(){
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++){
scanf("%s",op);scanf("%d%d",&u,&v);
if(op[0]=='A')link(u,v);
else{
cut(u,v);makeroot(u);makeroot(v);
printf("%lld\n",1ll*siz[u]*siz[v]);
link(u,v);
}
}
return 0;
}
点击查看K题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,ans;char op[5];
struct Disjoint_Set{
int fa[N],siz[N];
void init(int n){for(int i=1;i<=n;i++)fa[i]=i,siz[i]=1;}
int find(int x){return x==fa[x]?x:(fa[x]=find(fa[x]));}
void Union(int x,int y){x=find(x);y=find(y);if(x!=y)fa[x]=y,siz[y]+=siz[x];}
}S;
int fa[N],ch[N][2],tag[N],siz[N],siz2[N];
#define ls ch[x][0]
#define rs ch[x][1]
void push_up(int x){siz[x]=siz[ls]+siz[rs]+1+siz2[x];}
void make_tag(int x){if(!x)return;tag[x]^=1;swap(ls,rs);}
void push_down(int x){if(tag[x]){tag[x]=0;make_tag(ls);make_tag(rs);}}
bool get(int x){return x==ch[fa[x]][1];}
bool isroot(int x){return x!=ch[fa[x]][0]&&x!=ch[fa[x]][1];}
void update(int x){if(!isroot(x))update(fa[x]);push_down(x);}
void rotate(int x){
int y=fa[x],z=fa[y],op=get(x)^1;
if(!isroot(y))ch[z][get(y)]=x;
ch[y][op^1]=ch[x][op];if(ch[x][op])fa[ch[x][op]]=y;
ch[x][op]=y;fa[y]=x;fa[x]=z;push_up(y);push_up(x);
}
void splay(int x){
update(x);
for(int y=fa[x];!isroot(x);y=fa[x]){
if(!isroot(y))rotate(get(y)==get(x)?y:x);
rotate(x);
}
}
void access(int x){
for(int y=0;x;y=x,x=fa[x]){
splay(x);siz2[x]+=siz[ch[x][1]]-siz[y];
ch[x][1]=y;push_up(x);
}
}
int findroot(int x){access(x);splay(x);while(ls)push_down(x),x=ls;splay(x);return x;}
void makeroot(int x){access(x);splay(x);make_tag(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);ch[y][0]=fa[x]=0;push_up(y);}
void link(int x,int y){makeroot(x);makeroot(y);fa[x]=y;siz2[y]+=siz[x];}
int solve(int x){
int lsum=0,rsum=0,sum=siz[x]>>1,u=1e9,curl,curr;
while(x){
push_down(x);
curl=lsum+siz[ls];curr=rsum+siz[rs];
if(curl<=sum&&curr<=sum)u=min(u,x);
if(curl<curr)lsum+=siz[ls]+siz2[x]+1,x=rs;
else rsum+=siz[rs]+siz2[x]+1,x=ls;
}
splay(u);return u;
}
#undef ls
#undef rs
int main(){
scanf("%d%d",&n,&m);S.init(n);
for(int i=1;i<=n;i++)ans^=i;
while(m--){
scanf("%s",op);
if(op[0]=='A'){
int x,y;scanf("%d%d",&x,&y);
link(x,y);x=S.find(x);y=S.find(y);
split(x,y);int g=solve(y);
S.fa[x]=S.fa[y]=S.fa[g]=g;
ans^=x^y^g;
}
if(op[0]=='Q'){int x;scanf("%d",&x);printf("%d\n",S.find(x));}
if(op[0]=='X')printf("%d\n",ans);
}
return 0;
}