zoukankan      html  css  js  c++  java
  • Bzoj 4034: [HAOI2015]T2 树链剖分,子树问题,dfs序

    4034: [HAOI2015]T2

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1841  Solved: 598
    [Submit][Status][Discuss]

    Description

     有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个

    操作,分为三种:
    操作 1 :把某个节点 x 的点权增加 a 。
    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
     

    Input

     第一行包含两个整数 N, M 。表示点数和操作数。

    接下来一行 N 个整数,表示树中节点的初始权值。
    接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
    再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
    作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
     

    Output

     对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

     

    Sample Input

    5 5
    1 2 3 4 5
    1 2
    1 4
    2 3
    2 5
    3 3
    1 2 1
    3 5
    2 1 2
    3 3

    Sample Output

    6
    9
    13

    HINT

     对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不


    会超过 10^6 。

    Source

    鸣谢bhiaibogf提供

    题解:

    直接树链剖分。

    还有处理一下子树即可。(dfs序)。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define MAXN 100010
      4 #define LL long long
      5 struct node
      6 {
      7     int begin,end,next;
      8 }edge[2*MAXN];
      9 struct NODE
     10 {
     11     int left,right;
     12     LL sum,add;
     13 }tree[5*MAXN];
     14 int cnt,Head[MAXN],a[MAXN],size[MAXN],deep[MAXN],n,P[MAXN][17],pos[MAXN],belong[MAXN],ks[MAXN],js[MAXN],SIZE;
     15 bool vis[MAXN];
     16 void addedge(int bb,int ee)
     17 {
     18     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt;
     19 }
     20 void addedge1(int bb,int ee)
     21 {
     22     addedge(bb,ee);addedge(ee,bb);
     23 }
     24 int read()
     25 {
     26     int s=0,fh=1;char ch=getchar();
     27     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
     28     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
     29     return s*fh;
     30 }
     31 void dfs1(int u)
     32 {
     33     int i,v;
     34     size[u]=1;vis[u]=true;
     35     for(i=Head[u];i!=-1;i=edge[i].next)
     36     {
     37         v=edge[i].end;
     38         if(vis[v]==false)
     39         {
     40             deep[v]=deep[u]+1;
     41             P[v][0]=u;
     42             dfs1(v);
     43             size[u]+=size[v];
     44         }
     45     }
     46 }
     47 void Ycl()
     48 {
     49     int i,j;
     50     for(j=1;(1<<j)<=n;j++)
     51     {
     52         for(i=1;i<=n;i++)
     53         {
     54             if(P[i][j-1]!=-1)P[i][j]=P[P[i][j-1]][j-1];
     55         }
     56     }
     57 }
     58 void dfs2(int u,int chain)
     59 {
     60     int k=0,i,v;
     61     pos[u]=++SIZE;belong[u]=chain;ks[u]=SIZE;
     62     for(i=Head[u];i!=-1;i=edge[i].next)
     63     {
     64         v=edge[i].end;
     65         if(deep[v]>deep[u]&&size[v]>size[k])k=v;
     66     }
     67     if(k==0){js[u]=SIZE;return;}
     68     dfs2(k,chain);
     69     for(i=Head[u];i!=-1;i=edge[i].next)
     70     {
     71         v=edge[i].end;
     72         if(deep[v]>deep[u]&&v!=k)dfs2(v,v);
     73     }
     74     js[u]=SIZE;
     75 }
     76 void Pushup(int k)
     77 {
     78     tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
     79 }
     80 void Build(int k,int l,int r)
     81 {
     82     tree[k].left=l;tree[k].right=r;tree[k].add=0;
     83     if(l==r)return;//{tree[k].sum=a[l];return;}
     84     int mid=(l+r)/2;
     85     Build(k*2,l,mid);Build(k*2+1,mid+1,r);
     86     //Pushup(k);
     87 }
     88 /*void Pushup(int k)
     89 {
     90     tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
     91 }*/
     92 void Pushdown(int k)
     93 {
     94     int l=k*2,r=k*2+1,mid;
     95     if(tree[k].add!=0)
     96     {
     97         mid=(tree[k].left+tree[k].right)/2;
     98         tree[l].sum+=(LL)(mid-tree[k].left+1)*tree[k].add;
     99         tree[r].sum+=(LL)(tree[k].right-mid)*tree[k].add;
    100         tree[l].add+=tree[k].add;
    101         tree[r].add+=tree[k].add;
    102         tree[k].add=0;
    103     }
    104 }
    105 void Add(int k,int l,int r,int A)
    106 {
    107     if(l<=tree[k].left&&tree[k].right<=r){tree[k].add+=(LL)A;tree[k].sum+=(LL)(tree[k].right-tree[k].left+1)*A;return;}
    108     Pushdown(k);
    109     int mid=(tree[k].left+tree[k].right)/2;
    110     if(r<=mid)Add(k*2,l,r,A);
    111     else if(l>mid)Add(k*2+1,l,r,A);
    112     else {Add(k*2,l,mid,A);Add(k*2+1,mid+1,r,A);}
    113     Pushup(k);
    114 }
    115 LL Query_sum(int k,int l,int r)
    116 {
    117     if(l<=tree[k].left&&tree[k].right<=r)return (LL)tree[k].sum;
    118     Pushdown(k);
    119     int mid=(tree[k].left+tree[k].right)/2;
    120     if(r<=mid)return Query_sum(k*2,l,r);
    121     else if(l>mid)return Query_sum(k*2+1,l,r);
    122     else return Query_sum(k*2,l,mid)+Query_sum(k*2+1,mid+1,r);
    123     //Pushup(k);
    124 }
    125 LL Solve_sum(int x,int f)
    126 {
    127     LL sum=0;
    128     while(belong[x]!=belong[f])
    129     {
    130         sum+=Query_sum(1,pos[belong[x]],pos[x]);
    131         x=P[belong[x]][0];
    132     }
    133     sum+=Query_sum(1,pos[f],pos[x]);
    134     return sum;
    135 }
    136 int main()
    137 {
    138     int m,i,bb,ee,zs,k,k1;
    139     n=read();m=read();
    140     for(i=1;i<=n;i++)a[i]=read();
    141     memset(Head,-1,sizeof(Head));cnt=1;
    142     for(i=1;i<n;i++)
    143     {
    144         bb=read();ee=read();
    145         addedge1(bb,ee);
    146     }
    147     memset(P,-1,sizeof(P));SIZE=0;
    148     dfs1(1);Ycl();
    149     dfs2(1,1);
    150     Build(1,1,n);
    151     for(i=1;i<=n;i++)Add(1,pos[i],pos[i],a[i]);
    152     for(i=1;i<=m;i++)
    153     {
    154         zs=read();
    155         if(zs==1)
    156         {
    157             k=read();k1=read();Add(1,pos[k],pos[k],k1);
    158         }
    159         else if(zs==2)
    160         {
    161             k=read();k1=read();Add(1,ks[k],js[k],k1);
    162         }
    163         else
    164         {
    165             k=read();printf("%lld
    ",Solve_sum(k,1));
    166         }
    167     }
    168     return 0;
    169 }
  • 相关阅读:
    <2014 04 29> *nix环境编程常用库总结
    <2014 04 29> c/c++常用库总结
    <2014 04 26> 《Coders at Work编程人生:15位软件先驱访谈录》
    <2014 04 16> 上班实习第一天
    <2014 04 15> C++语言回顾精要(原创By Andrew)
    [荐][转]为何应该使用 MacOS X(论GUI环境下开发人员对软件的配置与重用)
    [荐][转]王垠:我和权威的故事(2014)
    [荐][转]如何用美剧真正提升你的英语水平
    [转] 数学的用处(一)(二)(三)(四)(数学图谱)
    metadata 和 routing
  • 原文地址:https://www.cnblogs.com/Var123/p/5311417.html
Copyright © 2011-2022 走看看