bzoj4034

ll卡了我半个小时

  1 #include<bits/stdc++.h>
  2 #define lowbit(a) ((a)&(-(a)))
  3 #define l(a) ((a)<<1)
  4 #define r(a) ((a)<<1|1) 
  5 #define clr(a,x) memset(a,x,sizeof(a))
  6 #define rep(i,l,r) for(int i=l;i<(r);i++)
  7 #define Rep(i,a) rep(i,0,e[a].size())
  8 typedef long long ll;
  9 using namespace std;
 10 int read()
 11 {
 12     char c=getchar();
 13     int ans=0,f=1;
 14     while(!isdigit(c)){
 15         if(c=='-') f=-1;
 16         c=getchar();
 17     }
 18     while(isdigit(c)){
 19         ans=ans*10+c-'0';
 20         c=getchar();
 21     }
 22     return ans*f;
 23 }
 24 struct node{
 25     ll l,r,sum,add;
 26 };
 27 const int maxn=100009,inf=0x3fffffff;
 28 int n,m,dfstime=0,w[maxn],f[maxn],son[maxn],top[maxn],dep[maxn],id[maxn],idr[maxn],L[maxn],R[maxn],size[maxn];
 29 node x[maxn<<2];
 30 vector<int>e[maxn];
 31 void dfs(int k){
 32     size[k]=1;
 33     Rep(i,k){
 34         int to=e[k][i];
 35         if(to==f[k]) continue;
 36         dep[to]=dep[k]+1;
 37         f[to]=k;
 38         dfs(to);
 39         size[k]+=size[to];
 40         if(!son[k]||size[son[k]]<size[to]) son[k]=to;
 41     }
 42 }
 43 int Top;
 44 void Dfs(int k){
 45     top[k]=Top;
 46     L[k]=id[k]=++dfstime;
 47     idr[id[k]]=k;
 48     if(son[k]) Dfs(son[k]);
 49     Rep(i,k){
 50         int to=e[k][i];
 51         if(id[to]) continue;
 52         Dfs(Top=to);
 53     }
 54     R[k]=dfstime;
 55 }
 56 void maintain(int k){
 57     x[k].sum=x[l(k)].sum+x[r(k)].sum;
 58 }
 59 void pushdown(int k){
 60     if(x[k].l==x[k].r){
 61         x[k].add=0;
 62         return;
 63     }
 64     if(!x[k].add) return;
 65     x[l(k)].sum+=(x[l(k)].r-x[l(k)].l+1)*x[k].add;
 66     x[r(k)].sum+=(x[r(k)].r-x[r(k)].l+1)*x[k].add;
 67     x[l(k)].add+=x[k].add;
 68     x[r(k)].add+=x[k].add;
 69     x[k].add=0;
 70 }
 71 void modify(int k,int l,int r,int t){
 72     pushdown(k);
 73     if(x[k].l==l&&x[k].r==r){
 74         x[k].add+=t;
 75         x[k].sum+=(ll)(r-l+1)*t;
 76         return;
 77     }
 78     int mid=(x[k].l+x[k].r)>>1;
 79     if(r<=mid) modify(l(k),l,r,t);
 80     else if(l>mid) modify(r(k),l,r,t);
 81     else{
 82         modify(l(k),l,mid,t);
 83         modify(r(k),mid+1,r,t);
 84     }
 85     maintain(k);
 86 }
 87 ll ask(int k,int l,int r){
 88     pushdown(k);
 89     if(x[k].l==l&&x[k].r==r) return x[k].sum;
 90     int mid=(x[k].l+x[k].r)>>1;
 91     if(r<=mid) return ask(l(k),l,r);
 92     if(l>mid) return ask(r(k),l,r);
 93     return ask(l(k),l,mid)+ask(r(k),mid+1,r);
 94 }
 95 void build(int k,int l,int r){
 96     x[k].l=l;x[k].r=r;x[k].add=0;
 97     if(l==r){
 98         x[k].sum=w[idr[l]];
 99         return;
100     }
101     int mid=(l+r)>>1;
102     build(l(k),l,mid);
103     build(r(k),mid+1,r);
104     maintain(k);
105 }
106 void addnode(int u,int t){
107     modify(1,id[u],id[u],t);
108 }
109 void addtree(int u,int t){
110     modify(1,L[u],R[u],t);
111 }
112 ll asksum(int u,int v){
113     ll ans=0;
114     while(top[u]!=top[v]){
115         if(dep[top[u]]<dep[top[v]]) swap(u,v);
116         ans+=ask(1,id[top[u]],id[u]);
117         u=f[top[u]];
118     }
119     if(dep[u]>dep[v]) swap(u,v);
120     ans+=ask(1,id[u],id[v]);
121     return ans;
122 }
123 void init(){
124     dfs(1);
125     Dfs(Top=1);
126     build(1,1,n);
127 }
128 int main()
129 {    
130     freopen("test.in","r",stdin);
131     freopen("my.out","w",stdout);
132     n=read(),m=read();
133     rep(i,1,n+1) w[i]=read();
134     rep(i,1,n){
135         int from=read(),to=read();
136         e[from].push_back(to);
137         e[to].push_back(from);
138     }
139     init();
140     while(m--){
141         int opt=read(),u=read(),v;
142         if(opt!=3) v=read();
143         if(opt==1) addnode(u,v);
144         else if(opt==2) addtree(u,v);
145         else printf("%lld\n",asksum(1,u));
146     }
147     return 0;
148 }
View Code

4034: [HAOI2015]T2

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 681  Solved: 253
[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-08-10 11:32  ChenThree  阅读(123)  评论(0编辑  收藏  举报