[国家集训队]旅游

题目描述

Ray 乐忠于旅游,这次他来到了T 城。T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有N − 1 座桥。

Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。有时,Ray 看待同一座桥的心情也会发生改变。

现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。

输入格式

输入的第一行包含一个整数N,表示T 城中的景点个数。景点编号为 0...N − 1。

接下来N − 1 行,每行三个整数u、v 和w,表示有一条u 到v,使 Ray 愉悦度增加w 的桥。桥的编号为1...N − 1。|w| <= 1000。 输入的第N + 1 行包含一个整数M,表示Ray 的操作数目。

接下来有M 行,每行描述了一个操作,操作有如下五种形式:

  • C i w,表示Ray 对于经过第i 座桥的愉悦度变成了w。

  • N u v,表示Ray 对于经过景点u 到v 的路径上的每一座桥的愉悦度都变成原来的相反数。

  • SUM u v,表示询问从景点u 到v 所获得的总愉悦度。

  • MAX u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最大愉悦度。

  • MIN u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最小愉悦度。

测试数据保证,任意时刻,Ray 对于经过每一座桥的愉悦度的绝对值小于等于1000。

输出格式

对于每一个询问(操作S、MAX 和MIN),输出答案。


 

是道水题,但好麻烦啊

注意释放取反标记时最大值的相反数是释放后最小值

同理

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

const int maxn=500005;
int n,m,tot,k=1,hd[maxn],val[maxn],ans;
int size[maxn],deep[maxn],fa[maxn],son[maxn];
int top[maxn],rev[maxn],sub[maxn];

struct node{
    int to,nt,val;
}e[maxn<<1];

inline void add(int x,int y,int val)
{
    e[++k].to=y;e[k].nt=hd[x];hd[x]=k;e[k].val=val;
    e[++k].to=x;e[k].nt=hd[y];hd[y]=k;e[k].val=val;
}

inline void dfs1(int x)
{
    deep[x]=deep[fa[x]]+1;
    size[x]=1;
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;
        if(!fa[v])
        {
            fa[v]=x;
            dfs1(v);
            val[v]=e[i].val;
            size[x]+=size[v];
            if(size[v]>size[son[x]])son[x]=v;
        }
    }
}


inline void dfs2(int x,int topf)
{
    top[x]=topf;
    sub[x]=++tot;
    rev[tot]=x;
    if(son[x])
    dfs2(son[x],topf);
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;
        if(!top[v])
            dfs2(v,v);
    }
}

#define ls rt<<1
#define rs rt<<1|1 
int maxx[maxn<<2],lazy[maxn<<2],sum[maxn<<2],minn[maxn<<2];

inline void pushup(int rt)
{
    sum[rt]=sum[ls]+sum[rs];
    maxx[rt]=max(maxx[ls],maxx[rs]);
    minn[rt]=min(minn[ls],minn[rs]); 
}
inline void build(int rt,int l,int r)
{
    if(l==r)
    {
        maxx[rt]=minn[rt]=sum[rt]=val[rev[l]];
        re ;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup(rt);
}

inline void pushdown(int rt)
{
    lazy[ls]^=1;lazy[rs]^=1;
    sum[ls]=-sum[ls];sum[rs]=-sum[rs];
    maxx[ls]^=minn[ls]^=maxx[ls]^=minn[ls];
    maxx[rs]^=minn[rs]^=maxx[rs]^=minn[rs];
    maxx[ls]=-maxx[ls];maxx[rs]=-maxx[rs];
    minn[ls]=-minn[ls];minn[rs]=-minn[rs];
    lazy[rt]^=1;
}


inline void change(int rt,int l,int r,int x,int add)
{
    if(l==r)
    {
        sum[rt]=maxx[rt]=minn[rt]=add;
        re ;
    }
    if(lazy[rt])pushdown(rt);
    int mid=(l+r)>>1;
    if(x<=mid)change(ls,l,mid,x,add);
    else change(rs,mid+1,r,x,add);
    pushup(rt); 
}

inline void reverse(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
    {
        sum[rt]=-sum[rt];
        maxx[rt]^=minn[rt]^=maxx[rt]^=minn[rt];
        maxx[rt]=-maxx[rt];minn[rt]=-minn[rt];
        lazy[rt]^=1;
        re ;
    }
    if(lazy[rt])pushdown(rt);
    int mid=(l+r)>>1;
    if(x<=mid)reverse(ls,l,mid,x,y);
    if(y>mid)reverse(rs,mid+1,r,x,y);
    pushup(rt);
}

inline void SUM(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
    {
        ans+=sum[rt];
        re ;
    }
    if(lazy[rt])pushdown(rt);
    int mid=(l+r)>>1;
    if(x<=mid)SUM(ls,l,mid,x,y);
    if(y>mid)SUM(rs,mid+1,r,x,y); 
}

inline void MAX(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
    {
        ans=max(ans,maxx[rt]);
        re ;
    }
    if(lazy[rt])pushdown(rt);
    int mid=(l+r)>>1;
    if(x<=mid)MAX(ls,l,mid,x,y);
    if(y>mid) MAX(rs,mid+1,r,x,y);
}


inline void MIN(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
    {
        ans=min(ans,minn[rt]);
        re ;
    }
    if(lazy[rt])pushdown(rt);
    int mid=(l+r)>>1;
    if(x<=mid)MIN(ls,l,mid,x,y);
    if(y>mid) MIN(rs,mid+1,r,x,y);
}

int main()
{
    int x,y,z;
    rd(n);
    inc(i,2,n) 
    {
        rd(x),rd(y),rd(z);
        add(x+1,y+1,z);
    }
    fa[1]=1;
    dfs1(1);
    dfs2(1,1);
    build(1,1,n);
    
    rd(m);
    char opt[10];
    inc(i,1,m)
    {
        scanf("%s",opt);
        rd(x),rd(y);
        ++x,++y;
        if(opt[0]=='C')
        {
            --x;--y;
            x=x<<1; 
            int a=e[x].to,b=e[x^1].to;
            if(deep[a]<deep[b])a^=b^=a^=b;
            change(1,1,n,sub[a],y);
        }
        else if(opt[0]=='N')
        {
            while(top[x]!=top[y])
            {
                if(deep[top[x]]<deep[top[y]])x^=y^=x^=y;
                reverse(1,1,n,sub[top[x]],sub[x]);
                x=fa[top[x]];
            }
            
            if(deep[x]>deep[y])x^=y^=x^=y;
            if(x!=y)
            reverse(1,1,n,sub[x]+1,sub[y]);
        }
        else if(opt[0]=='S')
        {
            ans=0;
            while(top[x]!=top[y])
            {
                if(deep[top[x]]<deep[top[y]])x^=y^=x^=y;
                SUM(1,1,n,sub[top[x]],sub[x]);
                x=fa[top[x]];
            }
            
            if(deep[x]>deep[y])x^=y^=x^=y;
            if(x!=y)
            SUM(1,1,n,sub[x]+1,sub[y]);
            printf("%d\n",ans);
        }
        else if(opt[1]=='A')
        {
            ans=-1000005;
            while(top[x]!=top[y])
            {
                if(deep[top[x]]<deep[top[y]])x^=y^=x^=y;
                MAX(1,1,n,sub[top[x]],sub[x]);
                x=fa[top[x]];
            }
            
            if(deep[x]>deep[y])x^=y^=x^=y;
            if(x!=y)
            MAX(1,1,n,sub[x]+1,sub[y]);
            printf("%d\n",ans);
        }
        else if(opt[1]=='I')
        {
            ans=1000045;
            while(top[x]!=top[y])
            {
                if(deep[top[x]]<deep[top[y]])x^=y^=x^=y;
                MIN(1,1,n,sub[top[x]],sub[x]);
                x=fa[top[x]];
            }
            
            if(deep[x]>deep[y])x^=y^=x^=y;
            if(x!=y)
            MIN(1,1,n,sub[x]+1,sub[y]);
            printf("%d\n",ans);
        }
    }
    re 0;
}

 

 

posted @ 2019-08-16 20:02  凉如水  阅读(106)  评论(0编辑  收藏  举报