zoukankan      html  css  js  c++  java
  • [国家集训队]旅游

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

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

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

    Solution

    调了一下午+一晚上,唉,代码能力实在不行。

    一眼链剖维护。

    线段树记一个最大值,最小值,区间和。

    犯的错:while写成if,单点修改时要把所有数据清空,标记下传时tag^=1,每次修改都要pushup。

    Code

    #include<iostream>
    #include<cstdio>
    #define N 200002
    #define inf 0x7f7f7f7f
    using namespace std;
    int size[N],head[N],son[N],tot,topo,top[N],fa[N],num[N],dfn[N],deep[N],n,ji[N],m,jj[N];
    char s[10];
    int tr[N<<2],ma[N<<2],mi[N<<2];
    bool la[N<<2]; 
    struct ff{
        int n,to,l,tag;
    }e[N<<1];
    inline void add(int u,int v,int l,int tag){
        e[++tot].n=head[u];
        e[tot].to=v;
        head[u]=tot;e[tot].l=l;e[tot].tag=tag;
    }
    void dfs(int u,int f){
        size[u]=1;
        for(int i=head[u];i;i=e[i].n)if(e[i].to!=f){
            int v=e[i].to;
            deep[v]=deep[u]+1;fa[v]=u;
            dfs(v,u);
            size[u]+=size[v];
            jj[e[i].tag]=v;
            num[v]=e[i].l;
            if(size[v]>size[son[u]])son[u]=v;
        }
    }
    void dfs2(int u){
        dfn[u]=++topo; 
        ji[topo]=u;
        if(!top[u])top[u]=u;
        if(son[u])top[son[u]]=top[u],dfs2(son[u]);
        for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa[u]&&e[i].to!=son[u])dfs2(e[i].to);
    }
    inline void pushdown(int cnt){
        tr[cnt<<1]*=-1;tr[cnt<<1|1]*=-1;
        ma[cnt<<1]*=-1;ma[cnt<<1|1]*=-1;
        mi[cnt<<1]*=-1;mi[cnt<<1|1]*=-1; 
        swap(ma[cnt<<1],mi[cnt<<1]);swap(ma[cnt<<1|1],mi[cnt<<1|1]);
        la[cnt]^=1;la[cnt<<1]^=1;la[cnt<<1|1]^=1;  
    } 
    void update2(int cnt,int l,int r,int L,int R){
        if(l>=L&&r<=R){
            tr[cnt]*=-1;mi[cnt]*=-1;ma[cnt]*=-1;la[cnt]^=1;
            swap(mi[cnt],ma[cnt]);
            return;
        }
        int mid=(l+r)>>1;
        if(la[cnt])pushdown(cnt);
        if(mid>=L)update2(cnt<<1,l,mid,L,R);
        if(mid<R) update2(cnt<<1|1,mid+1,r,L,R);
        tr[cnt]=tr[cnt<<1]+tr[cnt<<1|1];
        ma[cnt]=max(ma[cnt<<1],ma[cnt<<1|1]);
        mi[cnt]=min(mi[cnt<<1],mi[cnt<<1|1]); 
    }
    int query(int cnt,int l,int r,int L,int R,int tag){//0求和1最大值2最小值 
        if(l>=L&&r<=R){
          if(!tag)return tr[cnt];
          if(tag==1)return ma[cnt];
          return mi[cnt];
       }
        int mid=(l+r)>>1;
        if(la[cnt])pushdown(cnt);
        int ans=0,ans1=-inf,ans2=inf;
        if(mid>=L){
            int bi=query(cnt<<1,l,mid,L,R,tag);
            if(tag==0)ans+=bi;
            else if(tag==1)ans1=max(ans1,bi);
            else ans2=min(ans2,bi);
        }
        if(mid<R){
            int bi=query(cnt<<1|1,mid+1,r,L,R,tag);
            if(!tag)ans+=bi;
            else if(tag==1)ans1=max(ans1,bi);
            else ans2=min(ans2,bi);
        }
    //    tr[cnt]=tr[cnt<<1]+tr[cnt<<1|1];
    //    ma[cnt]=max(ma[cnt<<1],ma[cnt<<1|1]);
    //    mi[cnt]=min(mi[cnt<<1],mi[cnt<<1|1]);
        if(!tag)return ans;
        else if(tag==1)return ans1;
        else return ans2;
    }
    int que(int x,int y,int tag){
        int ans=0,ans1=-inf,ans2=inf;
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]])swap(x,y);
            if(!tag)ans+=query(1,2,topo,dfn[top[x]],dfn[x],tag);
            else if(tag==1)ans1=max(ans1,query(1,2,topo,dfn[top[x]],dfn[x],tag));
            else ans2=min(ans2,query(1,2,topo,dfn[top[x]],dfn[x],tag));
            x=fa[top[x]];
        }
        if(dfn[x]>dfn[y])swap(x,y);
        if(x!=y){
        if(!tag)ans+=query(1,2,topo,dfn[x]+1,dfn[y],tag);
            else if(tag==1)ans1=max(ans1,query(1,2,topo,dfn[x]+1,dfn[y],tag));
            else ans2=min(ans2,query(1,2,topo,dfn[x]+1,dfn[y],tag));
          }
        if(!tag)return ans;
        else if(tag==1)return ans1;
        else return ans2;
    }
    void update(int cnt,int l,int r,int x,int y){
        if(l==r){
            tr[cnt]=mi[cnt]=ma[cnt]=y;la[cnt]=0;
            return;
        }
        int mid=(l+r)>>1;
        if(la[cnt])pushdown(cnt);
        if(mid>=x)update(cnt<<1,l,mid,x,y);
        else update(cnt<<1|1,mid+1,r,x,y);
        tr[cnt]=tr[cnt<<1]+tr[cnt<<1|1];
        ma[cnt]=max(ma[cnt<<1],ma[cnt<<1|1]);
        mi[cnt]=min(mi[cnt<<1],mi[cnt<<1|1]); 
    }
    void work(int u,int v){
        while(top[u]!=top[v]){
            if(deep[top[u]]<deep[top[v]])swap(u,v);
            update2(1,2,topo,dfn[top[u]],dfn[u]);
            u=fa[top[u]]; 
        }
        if(dfn[u]>dfn[v])swap(u,v);
        if(u!=v)update2(1,2,topo,dfn[u]+1,dfn[v]);
    }
    void build(int cnt,int l,int r){
        if(l==r){
            tr[cnt]=ma[cnt]=mi[cnt]=num[ji[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(cnt<<1,l,mid);build(cnt<<1|1,mid+1,r);
        tr[cnt]=tr[cnt<<1]+tr[cnt<<1|1];
        ma[cnt]=max(ma[cnt<<1],ma[cnt<<1|1]);
        mi[cnt]=min(mi[cnt<<1],mi[cnt<<1|1]);
    }
    int main(){
    //    freopen("pus.in","r",stdin); 
    //    freopen("233.out","w",stdout);
        scanf("%d",&n);int u,v,w;
        for(int i=1;i<n;++i){
          scanf("%d%d%d",&u,&v,&w);
          u++;v++;add(u,v,w,i),add(v,u,w,i);
       }
        dfs(1,0);dfs2(1);
        build(1,2,topo);
        scanf("%d",&m); 
        while(m--){
            cin>>s;scanf("%d%d",&u,&v);++u,++v;
            if(s[0]=='C'){--u;--v;update(1,2,topo,dfn[jj[u]],v);}
            else if(s[0]=='N')work(u,v);
            else if(s[0]=='S')printf("%d
    ",que(u,v,0));
            else if(s[0]=='M'&&s[1]=='A')printf("%d
    ",que(u,v,1));
            else printf("%d
    ",que(u,v,2));
        }
        return 0;
    } 
  • 相关阅读:
    原码、反码、补码详解
    进制转换
    目录
    Window【目录】
    排序算法——冒泡排序
    算法的时间复杂度与空间复杂度
    排序算法
    递归—八皇后问题
    递归—迷宫问题
    递归
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9614870.html
Copyright © 2011-2022 走看看