zoukankan      html  css  js  c++  java
  • 月下“毛景树”

    Description
    毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:     Change k w:将第k条树枝上毛毛果的个数改变为w个。  Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。     Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:     Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
    Input
    第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。
    Output
    对于毛毛虫的每个询问操作,输出一个答案。
    Sample Input
    4
    1 2 8
    1 3 7
    3 4 9
    Max 2 4
    Cover 2 4 5
    Add 1 4 10
    Change 1 16
    Max 2 4
    Stop
    Sample Output
    9
    16
    【Data Range】
    1<=N<=100,000,操作+询问数目不超过100,000。
    保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。
    题面

    解题思路:边权化点权,将边权放到深度较深的点上面

    对于操作:
    Change k w:将第k条树枝上毛毛果的个数改变为w个。
    =>直接找对应的点,线段树上单点修改
    Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。
    =>注意:u和v的lca是不应该被修改的
    为了方便,我们可以先修改,再把lca改回去
    Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。
    =>注意:u和v的lca是不应该被加的
    为了方便,我们可以先修改,再把lca减回去
    Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
    =>注意:u和v的lca是不应该被算进去的
    我们可以先将lca赋成极小值
    得到答案后在将原值赋回去
    值得注意的地方是线段树的标记下放:
    先修改操作,后加操作,保证正确性

      1 #include<bits/stdc++.h>
      2 #define ll long long
      3 using namespace std;
      4 const ll N=1e5+10;
      5 struct node{
      6     ll u,v,c,ne;
      7 }e[N*2];
      8 ll h[N],tot,n;
      9 void add(ll u,ll v,ll c)
     10 {
     11     tot++;e[tot]=(node){u,v,c,h[u]};h[u]=tot;
     12     e[tot+n-1]=(node){v,u,c,h[v]};h[v]=tot+n-1;
     13 }
     14 ll dep[N],size[N],son[N],f[N];
     15 ll val[N],w[N],id[N],top[N];
     16 ll Max[N*6],ad[N*6],fg[N*6];
     17 void build(ll o,ll l,ll r)
     18 {
     19     fg[o]=-1;ad[o]=0;
     20     if(l==r){
     21         Max[o]=w[l];
     22         return;
     23     }
     24     ll mid=(l+r)>>1;
     25     build(o<<1,l,mid);build(o<<1|1,mid+1,r);
     26     Max[o]=max(Max[o<<1],Max[o<<1|1]);
     27 }
     28 void down(ll o)
     29 {
     30     if(fg[o]!=-1)
     31     {
     32         fg[o<<1]=Max[o<<1]=fg[o];
     33         fg[o<<1|1]=Max[o<<1|1]=fg[o];
     34         ad[o<<1]=ad[o<<1|1]=0;
     35         fg[o]=-1;
     36     }
     37     if(ad[o])
     38     {
     39         Max[o<<1]+=ad[o];Max[o<<1|1]+=ad[o];
     40         if(fg[o<<1]!=-1) fg[o<<1]+=ad[o];
     41         else ad[o<<1]+=ad[o];
     42         if(fg[o<<1|1]!=-1) fg[o<<1|1]+=ad[o];
     43         else ad[o<<1|1]+=ad[o];
     44         ad[o]=0;
     45     }
     46 }
     47 void tchange(ll o,ll l,ll r,ll x,ll y,ll k)
     48 {
     49     if(x<=l && y>=r)
     50     {
     51         Max[o]=k;fg[o]=k;ad[o]=0;
     52         return;
     53     }
     54     down(o);
     55     ll mid=(l+r)>>1;
     56     if(x<=mid) tchange(o<<1,l,mid,x,y,k);
     57     if(y>=mid+1) tchange(o<<1|1,mid+1,r,x,y,k);
     58     Max[o]=max(Max[o<<1],Max[o<<1|1]);
     59 }
     60 void tadd(ll o,ll l,ll r,ll x,ll y,ll k)
     61 {
     62     if(x<=l && y>=r)
     63     {
     64         ad[o]+=k;Max[o]+=k;
     65         return;
     66     }
     67     down(o);
     68     ll mid=(l+r)>>1;
     69     if(x<=mid) tadd(o<<1,l,mid,x,y,k);
     70     if(y>=mid+1) tadd(o<<1|1,mid+1,r,x,y,k);
     71     Max[o]=max(Max[o<<1],Max[o<<1|1]);
     72 }
     73 ll tquery(ll o,ll l,ll r,ll x,ll y)
     74 {
     75     if(x<=l && y>=r) return Max[o];
     76     down(o);
     77     ll mid=(l+r)>>1,tmp=-1e9;
     78     if(x<=mid) tmp=max(tmp,tquery(o<<1,l,mid,x,y));
     79     if(y>=mid+1) tmp=max(tmp,tquery(o<<1|1,mid+1,r,x,y));
     80     return tmp;
     81 }
     82 void dfs1(ll u)
     83 {
     84     size[u]=1;ll p=-1;
     85     for(ll i=h[u],rr;i;i=e[i].ne)
     86     {
     87         rr=e[i].v;
     88         if(!dep[rr])
     89         {
     90             dep[rr]=dep[u]+1;f[rr]=u;val[rr]=e[i].c;
     91             dfs1(rr);size[u]+=size[rr];
     92             if(size[rr]>p)
     93              p=size[rr],son[u]=rr;
     94         }
     95     }
     96 }
     97 void dfs2(ll u,ll up)
     98 {
     99     if(u==0) return;
    100     id[u]=++tot;w[tot]=val[u];
    101     top[u]=up;
    102     dfs2(son[u],up);
    103     for(ll i=h[u],rr;i;i=e[i].ne)
    104     {
    105         rr=e[i].v;
    106         if(rr!=f[u] && rr!=son[u]) dfs2(rr,rr);
    107     }
    108 }
    109 void Qchange(ll x,ll y,ll k)
    110 {
    111     while(top[x]!=top[y])
    112     {
    113         if(dep[top[x]]<dep[top[y]]) swap(x,y);
    114         tchange(1,1,n,id[top[x]],id[x],k);
    115         x=f[top[x]];
    116     }
    117     if(dep[x]>dep[y]) swap(x,y);
    118     tchange(1,1,n,id[x],id[y],k);
    119 }
    120 void Qadd(ll x,ll y,ll k)
    121 {
    122     while(top[x]!=top[y])
    123     {
    124         if(dep[top[x]]<dep[top[y]]) swap(x,y);
    125         tadd(1,1,n,id[top[x]],id[x],k);
    126         x=f[top[x]];
    127     }
    128     if(dep[x]>dep[y]) swap(x,y);
    129     tadd(1,1,n,id[x],id[y],k);
    130 }
    131 ll Qmax(ll x,ll y)
    132 {
    133     ll ans=-1;
    134     while(top[x]!=top[y])
    135     {
    136         if(dep[top[x]]<dep[top[y]]) swap(x,y);
    137         ans=max(ans,tquery(1,1,n,id[top[x]],id[x]));
    138         x=f[top[x]];
    139     }
    140     if(dep[x]>dep[y]) swap(x,y);
    141     ans=max(ans,tquery(1,1,n,id[x],id[y]));
    142     return ans;
    143 }
    144 ll lca(ll x,ll y)
    145 {
    146     while(top[x]!=top[y])
    147     {
    148         if(dep[top[x]]<dep[top[y]]) swap(x,y);
    149         x=f[top[x]];
    150     }
    151     if(dep[x]>dep[y]) swap(x,y);
    152     return x;
    153 }
    154 char op[10];
    155 ll x,y,z,fa,tmp;
    156 int main()
    157 {
    158     scanf("%lld",&n);
    159     for(ll i=1;i<=n-1;++i)
    160     {
    161         scanf("%lld%lld%lld",&x,&y,&z);
    162         add(x,y,z);
    163     }
    164     dep[1]=1;dfs1(1);
    165     val[1]=-1e9;tot=0;dfs2(1,1);
    166     build(1,1,n);
    167     while(scanf("%s",op)!=EOF)
    168     {
    169         if(op[1]=='t') break;
    170         if(op[1]=='h')//将第x条树枝上毛毛果的个数改变为y个
    171         {
    172             scanf("%lld%lld",&x,&y);
    173             x=(dep[e[x].u]>dep[e[x].v] ? e[x].u:e[x].v);
    174             tchange(1,1,n,id[x],id[x],y);
    175         }
    176         if(op[1]=='o')//将节点x与节点y之间的都改变为z个
    177         {
    178             scanf("%lld%lld%lld",&x,&y,&z);
    179             fa=lca(x,y);tmp=tquery(1,1,n,id[fa],id[fa]);
    180             Qchange(x,y,z);tchange(1,1,n,id[fa],id[fa],tmp);
    181         }
    182         if(op[1]=='d')//将节点x与节点y之间的都增加z个
    183         {
    184             scanf("%lld%lld%lld",&x,&y,&z);
    185             fa=lca(x,y);
    186             Qadd(x,y,z);tadd(1,1,n,id[fa],id[fa],-z);
    187         }
    188         if(op[1]=='a')//询问节点x与节点y之间最多有多少个
    189         {
    190             scanf("%lld%lld",&x,&y);
    191             fa=lca(x,y);tmp=tquery(1,1,n,id[fa],id[fa]);
    192             tchange(1,1,n,id[fa],id[fa],-1e9);
    193             printf("%lld
    ",Qmax(x,y));
    194             tchange(1,1,n,id[fa],id[fa],tmp);
    195         }
    196     }
    197     return 0;
    198 }
    代码
  • 相关阅读:
    八数码难题 (codevs 1225)题解
    小木棍 (codevs 3498)题解
    sliding windows (poj 2823) 题解
    集合删数 (vijos 1545) 题解
    合并果子 (codevs 1063) 题解
    等价表达式 (codevs 1107)题解
    生理周期 (poj 1006) 题解
    区间 (vijos 1439) 题解
    区间覆盖问题 题解
    种树 (codevs 1653) 题解
  • 原文地址:https://www.cnblogs.com/adelalove/p/8709620.html
Copyright © 2011-2022 走看看