bzoj2157 旅游——LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2157
仍然是LCT模板题~
不过有一些需要注意的地方,点和边的区分,0号点的 mx 和 mn 等等;
还有变成相反数的处理,要像线段树一样先修改再下传标记,那么查询时候就不用先 pushdown 了;
不过1A还是极好的~
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn=40005,inf=1005; int n,m,fa[maxn],mx[maxn],mn[maxn],sum[maxn],w[maxn],c[maxn][3],rev[maxn],tag[maxn],sta[maxn],top; bool isroot(int x){return c[fa[x]][0]!=x && c[fa[x]][1]!=x;} void pushup(int x) { int ls=c[x][0],rs=c[x][1]; sum[x]=sum[ls]+sum[rs]+w[x]; mx[x]=max(mx[ls],mx[rs]); mn[x]=min(mn[ls],mn[rs]); if(x<=n)return; mx[x]=max(mx[x],w[x]); mn[x]=min(mn[x],w[x]); } void tg(int x) { tag[x]^=1; w[x]=-w[x]; sum[x]=-sum[x]; swap(mx[x],mn[x]); mx[x]=-mx[x]; mn[x]=-mn[x]; } void pushdown(int x) { int ls=c[x][0],rs=c[x][1]; if(rev[x]) { rev[ls]^=1; rev[rs]^=1; rev[x]=0; swap(c[x][0],c[x][1]); } if(tag[x]) { tag[x]=0; if(ls)tg(ls); if(rs)tg(rs);// } } void rotate(int x) { int y=fa[x],z=fa[y],d=(c[y][1]==x); if(!isroot(y))c[z][c[z][1]==y]=x; fa[x]=z; fa[y]=x; fa[c[x][!d]]=y; c[y][d]=c[x][!d]; c[x][!d]=y; pushup(y); pushup(x); } void splay(int x) { sta[top=1]=x; for(int i=x;!isroot(i);i=fa[i])sta[++top]=fa[i]; for(;top;top--)pushdown(sta[top]); for(;!isroot(x);rotate(x)) { int y=fa[x],z=fa[y]; if(isroot(y))continue; ((c[y][0]==x)^(c[z][0]==y))?rotate(x):rotate(y); } } void access(int x) { for(int t=0;x;c[x][1]=t,pushup(x),t=x,x=fa[x])splay(x); } void makeroot(int x) { access(x); splay(x); rev[x]^=1; } void link(int x,int y) { makeroot(x); fa[x]=y; } void query(int x,int y) { makeroot(x); access(y); splay(y); } void change(int x,int t) { makeroot(x); w[x]=t; pushup(x); } int main() { scanf("%d",&n); mx[0]=-inf; mn[0]=inf;// for(int i=1,x,y,z;i<n;i++) { scanf("%d%d%d",&x,&y,&z); x++; y++; w[i+n]=z; link(x,i+n); link(y,i+n); } scanf("%d",&m); char ch[10]; for(int i=1,x,y;i<=m;i++) { scanf("%s%d%d",&ch,&x,&y); if(ch[0]=='C')change(x+n,y); else { x++; y++; query(x,y); if(ch[0]=='N')tg(y); if(ch[0]=='S')printf("%d\n",sum[y]); if(ch[1]=='A')printf("%d\n",mx[y]); if(ch[1]=='I')printf("%d\n",mn[y]); } } return 0; }