[HAOI2015]树上操作 -树链剖分

                                     1963. [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。

 

注意long long就好了 

把它当做树剖模板来做,听说并查集也能做

 

  1 #include <ctype.h>
  2 #include <cstdio>
  3 
  4 typedef long long LL;
  5 
  6 const int MAXN=100010;
  7 
  8 int n,m,inr;
  9 
 10 LL a[MAXN];
 11 
 12 struct SegmentTree {
 13     int l,r;
 14     LL val,tag;
 15 };
 16 SegmentTree t[MAXN<<2];
 17 
 18 struct data {
 19     int to;
 20     int next;
 21 };
 22 data E[MAXN*10];
 23 
 24 int head[MAXN<<1],tot;
 25 
 26 int siz[MAXN],son[MAXN],fa[MAXN],id[MAXN],dep[MAXN],top[MAXN],rank[MAXN],mx[MAXN];
 27 
 28 inline void read(int&x) {
 29     int f=1;register char c=getchar();
 30     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
 31     for(;isdigit(c);x=x*10+c-48,c=getchar());
 32     x=x*f;
 33 }
 34 
 35 inline void readl(LL&x) {
 36     int f=1;register char c=getchar();
 37     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
 38     for(;isdigit(c);x=x*10+c-48,c=getchar());
 39     x=x*f;
 40 }
 41 
 42 inline void add(int x,int y) {
 43     E[++tot].to=y;
 44     E[tot].next=head[x];
 45     head[x]=tot;
 46 }
 47 
 48 inline int max(int a,int b) {
 49     return a<b?b:a;
 50 }
 51 
 52 inline void swap(int&x,int&y) {
 53     int t=x;x=y;y=t;
 54     return;
 55 }
 56 
 57 inline void dfs_1(int now,int f) {
 58     dep[now]=dep[f]+1;
 59     siz[now]=1;
 60     fa[now]=f;
 61     for(register int i=head[now];i;i=E[i].next) {
 62         int to=E[i].to;
 63         if(to==f) continue;
 64         dfs_1(to,now);
 65         siz[now]+=siz[to];
 66         if(son[now]==-1||siz[son[now]]<siz[to]) son[now]=to;
 67     }
 68 }
 69 
 70 inline void dfs_2(int now,int sym) {
 71     id[now]=++inr;
 72     top[now]=sym;
 73     rank[id[now]]=now;
 74     if(son[now]==-1) return;
 75     dfs_2(son[now],sym);
 76     for(int i=head[now];i;i=E[i].next) {
 77         int to=E[i].to;
 78         if(to!=son[now]&&to!=fa[now])
 79           dfs_2(to,to);
 80     }
 81     return;
 82 }
 83 
 84 inline void build_tree(int now,int l,int r) {
 85     t[now].l=l,t[now].r=r;
 86     if(l==r) {
 87         t[now].val=a[rank[l]];
 88         return;
 89     }
 90     int mid=(l+r)>>1;
 91     build_tree(now<<1,l,mid);
 92     build_tree(now<<1|1,mid+1,r);
 93     t[now].val=t[now<<1].val+t[now<<1|1].val;
 94 }
 95 
 96 inline void down(int now) {
 97     t[now<<1].val+=(t[now<<1].r-t[now<<1].l+1)*t[now].tag;
 98     t[now<<1|1].val+=(t[now<<1|1].r-t[now<<1|1].l+1)*t[now].tag;
 99     t[now<<1].tag+=t[now].tag;
100     t[now<<1|1].tag+=t[now].tag;
101     t[now].tag=0;
102 }
103 
104 inline void modify(int now,int l,int r,LL val) {
105     if(l<=t[now].l&&r>=t[now].r) {
106         t[now].tag+=val;
107         t[now].val+=(t[now].r-t[now].l+1)*val;
108         return;
109     }
110     down(now);
111     int mid=(t[now].l+t[now].r)>>1;
112     if(l<=mid) modify(now<<1,l,r,val);
113     if(r>mid) modify(now<<1|1,l,r,val);
114     t[now].val=t[now<<1].val+t[now<<1|1].val;
115 }
116 
117 inline LL query(int now,int l,int r) {
118     LL ans=0;
119     if(l<=t[now].l&&r>=t[now].r) return t[now].val;
120     down(now);
121     int mid=(t[now].l+t[now].r)>>1;
122     if(l<=mid) ans+=query(now<<1,l,r);
123     if(r>mid) ans+=query(now<<1|1,l,r);
124     return ans;
125 }
126 
127 inline LL Pre_query(int u,int v) {
128     LL ans=0;
129     while(top[u]!=top[v]) {
130         if(dep[top[u]]<dep[top[v]]) swap(u,v);
131         ans+=query(1,id[top[u]],id[u]);
132         u=fa[top[u]];
133     }
134     if(dep[u]<dep[v]) swap(u,v);
135     ans+=query(1,id[v],id[u]);
136     return ans;
137 }
138 
139 int hh() {
140     freopen("haoi2015_t2.in","r",stdin);
141     freopen("haoi2015_t2.out","w",stdout);
142     int x,y,opt;
143     read(n);read(m);
144     for(register int i=1;i<=n;++i) son[i]=-1,readl(a[i]);
145     for(register int i=1;i<n;++i) {
146         read(x);read(y);
147         add(x,y);add(y,x);
148     }
149     dfs_1(1,0);
150     dfs_2(1,1);
151     build_tree(1,1,inr);
152     LL p;
153     for(register int i=1;i<=m;++i) {
154         read(opt);read(x);
155             if(opt==1) {
156                 readl(p);
157                 modify(1,id[x],id[x],p);
158             }
159             else if(opt==2) {
160                 readl(p);
161                 modify(1,id[x],id[x]+siz[x]-1,p);
162             }
163             else {
164                 LL ans=Pre_query(1,x);
165                 printf("%lld\n",ans);
166             }
167     }
168     return 0;
169 }
170 
171 int sb=hh();
172 int main() {;}
代码

 

posted @ 2017-08-22 08:56  拿叉插猹哈  阅读(171)  评论(0编辑  收藏  举报