[HAOI2015]树上操作

【题目描述】

有一棵点数为N的树,以点1为根,且树点有边权。然后有M个操作,分为三种:

操作1:把某个节点x的点权增加a。

操作2:把某个节点x为根的子树中所有点的点权都增加a。

操作3:询问某个节点x到根的路径中所有点的点权和。

【输入格式】

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

接下来一行N个整数,表示树中节点的初始权值。

接下来N-1行每行两个正整数fr,to,表示该树中存在一条边(fr,to)。

再接下来M行,每行分别表示一次操作。其中第一个数表示该操作的种类(1~3),之后接这个操作的参数(x或者x a)。

【输出格式】

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

【样例输入】

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

【样例输出】

6

9

13

【提示】

对于30%的数据,N,M<=1000

对于50%的数据,N,M<=100000且数据随机。

对于100%的数据,N,M<=100000,且所有输入数据的绝对值都不会超过10^6。

 

很有思考性的题,所以贴出来。

题解链接:http://www.cnblogs.com/Asm-Definer/p/4466729.html 

1操作直接在BIT 操作,

 

还要读入挂,OI真辛苦

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<math.h>
  4 #include<vector>
  5 #include<string.h>
  6 #include<string>
  7 #include<set>
  8 #include<iostream>
  9 using namespace std;
 10 typedef long long ll;
 11 #define N 153333
 12 
 13 vector<int>mp[N];
 14 int a[N],dep[N],st[N],ed[N],tot=1;
 15 ll f1[N],f2[N],c[N];
 16 int head[N];
 17 struct node
 18 {
 19     int v,next;
 20 }e[N<<1];
 21 int n,m;
 22 int lowbit(int x)
 23 {
 24     return x&-x;
 25 }
 26 
 27 void add1(int x,ll v)
 28 {
 29     for (int i=x;i<=n;i+=lowbit(i)) f1[i]+=v;
 30 }
 31 void add2(int x,ll v)
 32 {
 33     for (int i=x;i<=n;i+=lowbit(i)) f2[i]+=v;
 34 }
 35 ll query1(int x)
 36 {
 37     ll s=0;
 38     for (int i=x;i>0;i-=lowbit(i))
 39         s+=f1[i];
 40     return s;
 41 }
 42 ll query2(int x)
 43 {
 44     ll s=0;
 45     for (int i=x;i>0;i-=lowbit(i))
 46         s+=f2[i];
 47     return s;
 48 }
 49 
 50 void dfs(int u,int pre,int t,ll sum)
 51 {
 52     st[u]=tot++;
 53     dep[u]=t;
 54     sum+=a[u];
 55     c[u]=sum;
 56     for (int i=head[u];i!=-1;i=e[i].next)
 57     {
 58         int v=e[i].v;
 59         if (v==pre) continue;
 60         dfs(v,u,t+1,sum);
 61     }
 62     ed[u]=tot-1;
 63 }
 64 void judge()
 65 {
 66     freopen("haoi2015_t2.in","r",stdin);
 67     freopen("haoi2015_t2.out","w",stdout);
 68 
 69 }
 70 int tt;
 71 void add(int u,int v)
 72 {
 73     e[tt].v=v;
 74     e[tt].next=head[u];
 75     head[u]=tt++;
 76 }
 77 
 78 void Getz(int &x){
 79     int ch;
 80     while(ch=getchar(),ch<48||ch>57);x=ch-48;
 81     while(ch=getchar(),ch>47&&ch<58) x=x*10+ch-48;
 82 }
 83 int main()
 84 {
 85     judge();
 86     tt=0;
 87     memset(head,-1,sizeof(head));
 88     //scanf("%d%d",&n,&m);
 89     Getz(n); 
 90     Getz(m);
 91     for (int i=1;i<=n;i++) Getz(a[i]);
 92     for (int i=1;i<n;i++)
 93     {
 94         int x,y;
 95        // scanf("%d%d",&x,&y);
 96         Getz(x); Getz(y);
 97         //mp[x].push_back(y);
 98         add(x,y);
 99         add(y,x);
100         //mp[y].push_back(x);
101     }
102     dfs(1,-1,1,0);
103 //    for (int i=1;i<=n;i++)
104   //      cout<<st[i]<<" "<<ed[i]<<endl;
105 
106     while (m--)
107     {
108         int op,u,v;
109         scanf("%d",&op);
110         if (op==1)
111         {
112             //scanf("%d%d",&u,&v);
113             Getz(u); Getz(v);
114             add2(st[u],v);add2(ed[u]+1,-v);
115         }else if (op==2)
116         {
117             // scanf("%d%d",&u,&v);
118              Getz(u); Getz(v);
119              ll tmp=1-dep[u];
120              tmp*=v;
121              add1(st[u],v),add1(ed[u]+1,-v);
122              add2(st[u],tmp),add2(ed[u]+1,-tmp);
123         }
124         else
125         {
126              //scanf("%d",&u);
127              Getz(u);
128              printf("%lld\n",c[u]+query1(st[u])*dep[u]+query2(st[u]));
129         }
130     }
131 
132     return 0;

133 } 

posted on 2015-09-30 02:05  forgot93  阅读(291)  评论(0编辑  收藏  举报

导航