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;
}

 

posted @ 2018-06-29 16:25  Zinn  阅读(114)  评论(0编辑  收藏  举报