码迷,mamicode.com
首页 > 其他好文 > 详细

[国家集训队]旅游

时间:2018-09-09 20:32:46      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:lin   color   最大   能力   修改   void   标记   +=   using   

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\n",que(u,v,0));
        else if(s[0]==M&&s[1]==A)printf("%d\n",que(u,v,1));
        else printf("%d\n",que(u,v,2));
    }
    return 0;
} 

 

[国家集训队]旅游

标签:lin   color   最大   能力   修改   void   标记   +=   using   

原文地址:https://www.cnblogs.com/ZH-comld/p/9614870.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!