A[洛谷P3690]维护一个森林,支持询问路径xor和,连边(已连通则忽略),删边(无边则忽略),改变点权。
B[洛谷P3203]n个装置编号为0,...,n−1,从i可以一步跳到i+ki,支持修改ki,询问从一个点开始几步跳出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→min(i+ki,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; |
| } |
| |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验