UOJ 274 清华集训2016温暖会指引我们前行 ——Link-Cut Tree
Posted SfailSth ——Salt Fish
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UOJ 274 清华集训2016温暖会指引我们前行 ——Link-Cut Tree相关的知识,希望对你有一定的参考价值。
魔法森林高清重置,
只需要维护关于t的最大生成树,然后链上边权求和即可。
直接上LCT
调了将近2h
吃枣药丸
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define maxn 1000005 #define inf 0x3f3f3f3f struct Link_Cut_Tree{ int ch[maxn][2],fa[maxn],rev[maxn],mn[maxn],val[maxn],sum[maxn],len[maxn]; int sta[maxn],top; bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} void update(int x) { mn[x]=x; if (val[mn[ch[x][0]]]<val[mn[x]]) mn[x]=mn[ch[x][0]]; if (val[mn[ch[x][1]]]<val[mn[x]]) mn[x]=mn[ch[x][1]]; sum[x]=len[x]+sum[ch[x][0]]+sum[ch[x][1]]; } void pushdown (int x) { if (rev[x]) { rev[x]^=1; rev[ch[x][0]]^=1; rev[ch[x][1]]^=1; swap(ch[x][0],ch[x][1]); } } void rot(int x) { int y=fa[x],z=fa[y],l,r; if (ch[y][0]==x) l=0; else l=1; r=l^1; if (!isroot(y)) { if (ch[z][0]==y) ch[z][0]=x; else ch[z][1]=x; } fa[x]=z; fa[y]=x; fa[ch[x][r]]=y; ch[y][l]=ch[x][r]; ch[x][r]=y; update(y);update(x); } void splay(int x) { top=0;sta[++top]=x; for (int i=x;!isroot(i);i=fa[i]) sta[++top]=fa[i]; while (top) pushdown(sta[top--]); while (!isroot(x)) { int y=fa[x],z=fa[y]; if (!isroot(y)) { if (ch[z][0]==y^ch[y][0]==x) rot(x); else rot(y); } rot(x); } } void access(int x) { for (int t=0;x;t=x,x=fa[x]) splay(x),ch[x][1]=t,update(x); } void makeroot(int x) { access(x); splay(x); rev[x]^=1; } int find(int x) { access(x); splay(x); while (ch[x][0]) x=ch[x][0]; return x; } void link(int x,int y) { makeroot(x); fa[x]=y; } void cut(int x,int y) { makeroot(x); access(y); ch[y][0]=0; fa[x]=0; } int query(int x,int y) { if (find(x)!=find(y)) return -1; makeroot(x);access(y);splay(y); return sum[y]; } int qmn(int x,int y) { makeroot(x);access(y);splay(y); return mn[y]; } void modify(int x,int l) { access(x);splay(x); len[x]=l;update(x); } }LCT; int n,m,u[maxn],v[maxn],id,t,l,x,y,in[maxn]; char opt[11]; int main() { scanf("%d%d",&n,&m); F(i,0,n) LCT.val[i]=inf; F(i,1,m) { scanf("%s",opt); switch(opt[0]) { case ‘f‘: scanf("%d",&id); id++; scanf("%d%d%d%d",&u[id],&v[id],&t,&l);u[id]++;v[id]++; LCT.len[id+n]=l;LCT.val[id+n]=t;LCT.mn[id+n]=id+n; if (LCT.find(u[id])!=LCT.find(v[id])) { LCT.link(id+n,u[id]); LCT.link(id+n,v[id]); in[id]=1; } else { int tmp=LCT.qmn(u[id],v[id]); if (LCT.val[tmp]<t) { LCT.cut(u[tmp-n],tmp); LCT.cut(v[tmp-n],tmp); in[tmp-n]=0; LCT.link(id+n,u[id]); LCT.link(id+n,v[id]); in[id]=1; } } break; case ‘m‘: scanf("%d%d",&x,&y);x++;y++; printf("%d\n",LCT.query(x,y)); break; case ‘c‘: scanf("%d%d",&id,&l); id++; if (in[id]) LCT.modify(id+n,l); break; } } }
以上是关于UOJ 274 清华集训2016温暖会指引我们前行 ——Link-Cut Tree的主要内容,如果未能解决你的问题,请参考以下文章
UOJ274 [清华集训2016] 温暖会指引我们前行 LCT最大生成树