bzoj 4034 [HAOI2015] T2(树链剖分,线段树)
2016-02-11 16:55
417 查看
4034: [HAOI2015]T2
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1536 Solved: 508
[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 51 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
69
13
HINT
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。
Source
鸣谢bhiaibogf提供【思路】
树链剖分,线段树
线段树:区间和,区间修改add
【代码】
#include<cstdio> #include<cstring> #include<vector> #include<iostream> #include<algorithm> #define FOR(a,b,c) for(int a=(b);a<=(c);a++) using namespace std; typedef long long LL; const int N = 400000+10; struct Node { LL sum,addv; }T[N<<1]; int n,q,z,c ; vector<int> g ; //INIT int top ,son ,dep ,fa ,siz ,w ,mxw ; void dfs1(int u) { son[u]=0; siz[u]=1; for(int i=0;i<g[u].size();i++) { int v=g[u][i]; if(v!=fa[u]) { fa[v]=u , dep[v]=dep[u]+1; dfs1(v); siz[u]+=siz[v]; if(siz[v]>siz[son[u]]) son[u]=v; } } } void dfs2(int u,int tp) { top[u]=tp; w[u]=mxw[u]=++z; if(son[u]) dfs2(son[u],tp),mxw[u]=max(mxw[u],mxw[son[u]]); for(int i=0;i<g[u].size();i++) { int v=g[u][i]; if(v!=fa[u] && v!=son[u]) dfs2(v,v),mxw[u]=max(mxw[u],mxw[v]); } } //SEGMENT TREE void pushdown(int u,int l,int r) { if(T[u].addv && l<r) { int lc=u<<1,rc=lc|1,M=(l+r)>>1; T[lc].sum+=T[u].addv*(M-l+1); T[rc].sum+=T[u].addv*(r-M); T[lc].addv+=T[u].addv,T[rc].addv+=T[u].addv; T[u].addv=0; } } void update(int u,int L,int R,int l,int r,int x) { pushdown(u,L,R); if(l<=L && R<=r) T[u].addv+=x , T[u].sum+=x*(R-L+1); else { int M=(L+R)>>1,lc=u<<1,rc=lc|1; if(l<=M) update(lc,L,M,l,r,x); if(M<r) update(rc,M+1,R,l,r,x); T[u].sum=T[lc].sum+T[rc].sum; } } LL query(int u,int L,int R,int l,int r) { pushdown(u,L,R); if(l<=L && R<=r) return T[u].sum; else { int M=(L+R)>>1; LL ans=0; if(l<=M) ans+=query(u<<1,L,M,l,r); if(M<r) ans+=query(u<<1|1,M+1,R,l,r); return ans; } } //Ê÷Á´ÆÊ·Ö LL query(int u) { LL sum=0; while(top[u]!=1) { sum+=query(1,1,z,w[top[u]],w[u]); u=fa[top[u]]; } sum+=query(1,1,z,1,w[u]); return sum; } void read(int& x) { char c=getchar(); int f=1; x=0; while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();} while(isdigit(c)) x=x*10+c-'0',c=getchar(); x*=f; } int main() { //freopen("in.in","r",stdin); //freopen("out.in","w",stdout); read(n),read(q); FOR(i,1,n) read(c[i]); int u,v,x,op,y; FOR(i,1,n-1) { read(u),read(v); g[u].push_back(v); g[v].push_back(u); } dfs1(1),dfs2(1,1); FOR(i,1,n) update(1,1,z,w[i],w[i],c[i]); while(q--) { read(op),read(x); if(op==1) read(y),update(1,1,z,w[x],w[x],y); else if(op==2) read(y),update(1,1,z,w[x],mxw[x],y); else printf("%lld\n",query(x)); } return 0; }
View Code
相关文章推荐
- 【JMeter】常用后置处理器性能比较(上)
- 运用BaseAdapter自定义一个经典的ListView
- Hdu 2018 母牛的故事 简单DP
- Javascript中的设置事件/事件对象及事件对象作用
- Light OJ 1110 An Easy LCS (DP+路径记录)
- Hibernate【3】(session和sessionFactory)
- hdu1224Free DIY Tour【最大子序列dp】
- 【字符串】Reverse Words in a String(两个栈)
- java数据类型
- 指针基础1
- scala中的this.type
- gearman 总结
- struts2学习笔记--OGNL表达式1
- Hdu 2084 数塔 简单DP
- Java核心技术(第8版)学习笔记_基本的程序设计结构
- 彭博亿万富豪排名
- 从初识Linux到离不开系列(三)悠然而生
- 1018. 锤子剪刀布 (20)
- Java的多线程之同步篇一:锁对象、条件对象
- bzoj3196 二逼平衡树