• Bzoj 1984: 月下“毛景树” 树链剖分


    1984: 月下“毛景树”

    Time Limit: 20 Sec  Memory Limit: 64 MB
    Submit: 1282  Solved: 410
    [Submit][Status][Discuss]

    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个。

    HINT

     

    Source

     题解:
    挺好的一道题。(处理边权的经典题)
    其实就是把每条边上的权值放到这条边下方的点上即可。(这里Orz Popoqqq)
    然后就是直接树链剖分即可。。。
    但是一定要打标记。(两个标记:add和cover标记。)
    而且,一定要先处理 覆盖标记 ,再处理 加数标记 。
    因为询问时比如到了[l,r]区间,[l,r]区间原来的标记已经被下传过了。(就是如果原来有add标记,我现在要打个cover标记时,原来的add标记就要被清空。)所以询问时先覆盖,再加数。(加数一定是在覆盖后的数上加。)
    然后用线段树维护一下即可。。。
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define MAXN 100010
      4 #define INF 1e9
      5 struct node
      6 {
      7     int begin,end,next;
      8 }edge[MAXN*2];
      9 struct NODE
     10 {
     11     int left,right,a,c,mx;
     12 }tree[MAXN*5];
     13 int cnt,Head[MAXN],pos[MAXN],size[MAXN],deep[MAXN],P[MAXN][17],chain[MAXN],belong[MAXN],id[MAXN],vv[MAXN],UU[MAXN],VV[MAXN],WW[MAXN],SIZE,n;
     14 bool vis[MAXN];
     15 void addedge(int bb,int ee)
     16 {
     17     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt;
     18 }
     19 void addedge1(int bb,int ee)
     20 {
     21     addedge(bb,ee);addedge(ee,bb);
     22 }
     23 int read()
     24 {
     25     int s=0,fh=1;char ch=getchar();
     26     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
     27     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
     28     return s*fh;
     29 }
     30 void dfs1(int u)
     31 {
     32     int i,v;
     33     size[u]=1;vis[u]=true;
     34     for(i=Head[u];i!=-1;i=edge[i].next)
     35     {
     36         v=edge[i].end;
     37         if(vis[v]==false)
     38         {
     39             deep[v]=deep[u]+1;
     40             P[v][0]=u;
     41             dfs1(v);
     42             size[u]+=size[v];
     43         }
     44     }
     45 }
     46 void Ycl()
     47 {
     48     int i,j;
     49     for(j=1;(1<<j)<=n;j++)
     50     {
     51         for(i=1;i<=n;i++)
     52         {
     53             if(P[i][j-1]!=-1)P[i][j]=P[P[i][j-1]][j-1];
     54         }
     55     }
     56 }
     57 void dfs2(int u,int chain)
     58 {
     59     int k=0,i,v;
     60     pos[u]=++SIZE;belong[u]=chain;
     61     for(i=Head[u];i!=-1;i=edge[i].next)
     62     {
     63         v=edge[i].end;
     64         if(deep[v]>deep[u]&&size[v]>size[k])k=v;
     65     }
     66     if(k==0)return;
     67     dfs2(k,chain);
     68     for(i=Head[u];i!=-1;i=edge[i].next)
     69     {
     70         v=edge[i].end;
     71         if(deep[v]>deep[u]&&v!=k)dfs2(v,v);
     72     }
     73 }
     74 int LCA(int x,int y)
     75 {
     76     int i,j;
     77     if(deep[x]<deep[y])swap(x,y);
     78     for(i=0;(1<<i)<=deep[x];i++);i--;
     79     for(j=i;j>=0;j--)if(deep[x]-(1<<j)>=deep[y])x=P[x][j];
     80     if(x==y)return x;
     81     for(j=i;j>=0;j--)
     82     {
     83         if(P[x][j]!=-1&&P[x][j]!=P[y][j])
     84         {
     85             x=P[x][j];
     86             y=P[y][j];
     87         }
     88     }
     89     return P[x][0];
     90 }
     91 void Pushup(int k)
     92 {
     93     tree[k].mx=max(tree[k*2].mx,tree[k*2+1].mx);
     94 }
     95 void Update1(int k,int k1)
     96 {
     97     tree[k].mx=k1;tree[k].a=0;tree[k].c=k1;
     98 }
     99 void Update2(int k,int k1)
    100 {
    101     tree[k].a+=k1;tree[k].mx+=k1;
    102 }
    103 void Pushdown(int k)
    104 {
    105     int l=k*2,r=k*2+1;
    106     if(tree[k].c!=-1)
    107     {
    108         Update1(l,tree[k].c);Update1(r,tree[k].c);
    109         tree[k].c=-1;
    110     }
    111     if(tree[k].a!=0)
    112     {
    113         Update2(l,tree[k].a);Update2(r,tree[k].a);
    114         tree[k].a=0;
    115     }
    116 }
    117 void Build(int k,int l,int r)
    118 {
    119     tree[k].left=l;tree[k].right=r;tree[k].c=-1;tree[k].a=0;
    120     if(l==r){tree[k].mx=vv[l];return;}
    121     int mid=(l+r)/2;
    122     Build(k*2,l,mid);Build(k*2+1,mid+1,r);
    123     Pushup(k);
    124 }
    125 int Query_max(int k,int l,int r)
    126 {
    127     if(l<=tree[k].left&&tree[k].right<=r)return tree[k].mx;
    128     Pushdown(k);
    129     int mid=(tree[k].left+tree[k].right)/2;
    130     if(r<=mid)return Query_max(k*2,l,r);
    131     else if(l>mid)return Query_max(k*2+1,l,r);
    132     else return max(Query_max(k*2,l,mid),Query_max(k*2+1,mid+1,r));
    133 }
    134 void Add(int k,int l,int r,int A)
    135 {
    136     if(l<=tree[k].left&&tree[k].right<=r){tree[k].a+=A;tree[k].mx+=A;return;}
    137     Pushdown(k);
    138     int mid=(tree[k].left+tree[k].right)/2;
    139     if(r<=mid)Add(k*2,l,r,A);
    140     else if(l>mid)Add(k*2+1,l,r,A);
    141     else {Add(k*2,l,mid,A);Add(k*2+1,mid+1,r,A);}
    142     Pushup(k);
    143 }
    144 void Cover(int k,int l,int r,int C)
    145 {
    146     if(l<=tree[k].left&&tree[k].right<=r){tree[k].c=C;tree[k].a=0;tree[k].mx=C;return;}
    147     Pushdown(k);
    148     int mid=(tree[k].left+tree[k].right)/2;
    149     if(r<=mid)Cover(k*2,l,r,C);
    150     else if(l>mid)Cover(k*2+1,l,r,C);
    151     else {Cover(k*2,l,mid,C);Cover(k*2+1,mid+1,r,C);}
    152     Pushup(k);
    153 }
    154 int Solve_max(int x,int f)
    155 {
    156     int MAX=-INF;
    157     while(belong[x]!=belong[f])
    158     {
    159         MAX=max(MAX,Query_max(1,pos[belong[x]],pos[x]));
    160         x=P[belong[x]][0];
    161     }
    162     if(f!=x)MAX=max(MAX,Query_max(1,pos[f]+1,pos[x]));
    163     return MAX;
    164 }
    165 void Solve_add(int x,int f,int add)
    166 {
    167     while(belong[x]!=belong[f])
    168     {
    169         Add(1,pos[belong[x]],pos[x],add);
    170         x=P[belong[x]][0];
    171     }
    172     if(x!=f)Add(1,pos[f]+1,pos[x],add);
    173 }
    174 void Solve_cover(int x,int f,int cover)
    175 {
    176     while(belong[x]!=belong[f])
    177     {
    178         Cover(1,pos[belong[x]],pos[x],cover);
    179         x=P[belong[x]][0];
    180     }
    181     if(x!=f)Cover(1,pos[f]+1,pos[x],cover);
    182 }
    183 int main()
    184 {
    185     int i,U,V,W,lca,k;
    186     char zs[10];
    187     n=read();
    188     memset(Head,-1,sizeof(Head));cnt=1;
    189     for(i=1;i<n;i++){UU[i]=read(),VV[i]=read(),WW[i]=read();addedge1(UU[i],VV[i]);}
    190     memset(P,-1,sizeof(P));SIZE=0;
    191     dfs1(1);Ycl();
    192     dfs2(1,1);
    193     memset(id,0,sizeof(id));
    194     for(i=1;i<n;i++)//存储每条边下方的点.
    195     {
    196         if(deep[UU[i]]>deep[VV[i]])id[i]=UU[i];
    197         else id[i]=VV[i];
    198     }
    199     for(i=1;i<n;i++)vv[pos[id[i]]]=WW[i];
    200     Build(1,1,n);
    201     while(1)
    202     {
    203         scanf("
    %s",zs);
    204         if(zs[0]=='S')break;
    205         if(zs[0]=='M')
    206         {
    207             U=read();V=read();
    208             lca=LCA(U,V);
    209             printf("%d
    ",max(Solve_max(U,lca),Solve_max(V,lca)));
    210         }
    211         else if(zs[0]=='A')
    212         {
    213             U=read();V=read();W=read();
    214             lca=LCA(U,V);
    215             Solve_add(U,lca,W);Solve_add(V,lca,W);
    216         }
    217         else
    218         {
    219             if(zs[1]=='o')
    220             {
    221                 U=read();V=read();W=read();
    222                 lca=LCA(U,V);
    223                 Solve_cover(U,lca,W);Solve_cover(V,lca,W);
    224             }
    225             else
    226             {
    227                 k=read();W=read();
    228                 vv[pos[id[k]]]=W;
    229                 Cover(1,pos[id[k]],pos[id[k]],W);
    230             }
    231         }
    232     }
    233     return 0;
    234 }
  • 相关阅读:
    Cookie:Session,ServletContext
    thrift安装笔记
    Maven笔记
    JVM 几个重要的参数
    dbvisualizer参数设置
    Linux中如何设置java环境变量
    java.net.NoRouteToHostException: No route to host
    新上海滩感想
    也许你的种子永远不会开花,因为他是一棵参天大树
    男子给妻子做了张桌子,他病逝后家人偶然发现...
  • 原文地址:https://www.cnblogs.com/Var123/p/5311392.html
Copyright © 2020-2023  润新知