【BZOJ】【4034】【HAOI2015】T2

树链剖分/dfs序


  树上单点修改+子树修改+链查询

  其实用dfs序做也可以……

  其实树链剖分就是一个特殊的dfs序嘛= =所以树链剖分也可以搞子树~(Orz ZYF)

  至于为什么……你看在做剖分的时候不也是dfs下去的?然后只不过是先走重儿子,但本质上也是一个dfs序,所以dfs序能搞的子树操作,链剖也是兹瓷的~

  然后随便水水就过了……

  WA了一发:查询从x到1的权值和的时候,写成了while(top[x]),改成while(x)后就过了……

  1 /**************************************************************
  2     Problem: 4034
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:2192 ms
  7     Memory:27956 kb
  8 ****************************************************************/
  9  
 10 //BZOJ 4034
 11 #include<vector>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<cstdlib>
 15 #include<iostream>
 16 #include<algorithm>
 17 #define rep(i,n) for(int i=0;i<n;++i)
 18 #define F(i,j,n) for(int i=j;i<=n;++i)
 19 #define D(i,j,n) for(int i=j;i>=n;--i)
 20 #define pb push_back
 21 using namespace std;
 22 inline int getint(){
 23     int v=0,sign=1; char ch=getchar();
 24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
 25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
 26     return v*sign;
 27 }
 28 const int N=2e5+10,INF=~0u>>2;
 29 typedef long long LL;
 30 /******************tamplate*********************/
 31  
 32  
 33 int to[N<<1],nxt[N<<1],head[N],cnt;
 34 void add(int x,int y){
 35     to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt;
 36     to[++cnt]=x; nxt[cnt]=head[y]; head[y]=cnt;
 37 }
 38 LL n,m,a[N];
 39 LL sm[N<<2],ad[N<<2];
 40 #define mid (l+r>>1)
 41 #define L (o<<1)
 42 #define R (o<<1|1)
 43 inline void maintain(int o,int l,int r){
 44     sm[o]=sm[L]+sm[R];
 45 }
 46 inline void Push_down(int o,int l,int r){
 47     if (ad[o]) {
 48         ad[L]+=ad[o]; sm[L]+=ad[o]*(mid-l+1);
 49         ad[R]+=ad[o]; sm[R]+=ad[o]*(r-mid);
 50         ad[o]=0;
 51     }
 52 }
 53 void update(int o,int l,int r,int ql,int qr,LL v){
 54     if (ql<=l && qr>=r) sm[o]+=v*(LL)(r-l+1),ad[o]+=v;
 55     else{
 56         Push_down(o,l,r);
 57         if (ql<=mid) update(L,l,mid,ql,qr,v);
 58         if (qr>mid) update(R,mid+1,r,ql,qr,v);
 59         maintain(o,l,r);
 60     }
 61 }
 62 LL query_it(int o,int l,int r,int ql,int qr){
 63     if (ql<=l && qr>=r) return sm[o];
 64     else{
 65         LL ans=0; Push_down(o,l,r);
 66         if (ql<=mid) ans+=query_it(L,l,mid,ql,qr);
 67         if (qr>mid) ans+=query_it(R,mid+1,r,ql,qr);
 68         return ans;
 69     }
 70 }
 71  
 72 int top[N],fa[N],dep[N],tid[N],st[N],ed[N],son[N],size[N];
 73 void dfs(int x){
 74     size[x]=1; son[x]=0;
 75     int mx=0;
 76     for(int i=head[x];i;i=nxt[i])
 77         if (to[i]!=fa[x]){
 78             fa[to[i]]=x;
 79             dep[to[i]]=dep[x]+1;
 80             dfs(to[i]);
 81             size[x]+=size[to[i]];
 82             if (size[to[i]]>mx) mx=size[to[i]],son[x]=to[i];
 83         }
 84 }
 85 int tot;
 86 bool vis[N];
 87 void connect(int x,int f){
 88     vis[x]=1;
 89     top[x]=f;
 90     st[x]=tid[x]=++tot;
 91     if (son[x]) connect(son[x],f);
 92     for(int i=head[x];i;i=nxt[i])
 93         if (!vis[to[i]])
 94             connect(to[i],to[i]);
 95     ed[x]=tot;
 96 }
 97 LL query(int x){
 98     LL ans=0;
 99     while(x){
100         ans+=query_it(1,1,n,tid[top[x]],tid[x]);
101         x=fa[top[x]];
102     }
103     return ans;
104 }
105 int main(){
106 #ifndef ONLINE_JUDGE
107     freopen("4034.in","r",stdin);
108     freopen("4034.out","w",stdout);
109 #endif
110     n=getint(); m=getint();
111     F(i,1,n) a[i]=getint();
112     F(i,2,n){
113         int x=getint(),y=getint();
114         add(x,y);
115     }
116     dfs(1);
117     connect(1,1);
118     F(i,1,n) update(1,1,n,tid[i],tid[i],a[i]);
119     int cmd,x,y;
120     F(i,1,m){
121         cmd=getint(); x=getint();
122         if (cmd==1){
123             y=getint();
124             update(1,1,n,tid[x],tid[x],y);
125         }else if (cmd==2){
126             y=getint();
127             update(1,1,n,st[x],ed[x],y);
128         }else{
129             printf("%lld\n",query(x));
130         }
131     }
132     return 0;
133 }
View Code

4034: [HAOI2015]T2

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 265  Solved: 113
[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

[Submit][Status][Discuss]
posted @ 2015-05-12 21:39  Tunix  阅读(482)  评论(0编辑  收藏  举报