HDU 3966 基础树链剖分
2015-08-27 17:21
218 查看
题意:给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 50010 #define ls o<<1 #define rs o<<1|1 #define define_m int m=(l+r)>>1 #define ll long long int n , m , q , first , k; struct Edge{ int y , next; Edge(){} Edge(int y , int next):y(y),next(next){} }e[N<<1]; void add_edge(int x , int y) { e[k] = Edge(y , first[x]); first[x] = k++; } int sz , fa , son , top , dep , id , number; void dfs(int u , int f , int d) { fa[u] = f; sz[u] = 1 , dep[u] = d , son[u] =0; int maxn = 0; for(int i=first[u] ; ~i ; i=e[i].next){ int v= e[i].y; if(v == f) continue; dfs(v , u , d+1); sz[u] += sz[v]; if(sz[v]>maxn) son[u] = v , maxn=sz[v]; } } void dfs1(int u , int f , int head) { top[u] = head; if(son[u]){ id[son[u]] = ++number; dfs1(son[u] , u , head); } for(int i=first[u] ; ~i ; i=e[i].next){ int v = e[i].y; if(v == f || v == son[u]) continue; id[v] = ++number; dfs1(v , u , v); } } int val , add[N<<2] , siz[N<<2]; ll sum[N<<2]; void push_up(int o){sum[o] = sum[ls]+sum[rs];} void push_down(int o) { if(add[o]){ add[ls] += add[o] , add[rs] += add[o]; sum[ls] += (ll)add[o]*siz[ls] , sum[rs] += (ll)add[o]*siz[rs]; add[o] = 0; } } void build(int o , int l , int r) { add[o] = 0 , siz[o] = r-l+1; if(l==r){ sum[o] = (ll)val[l]; return ; } define_m; build(ls , l , m); build(rs , m+1 , r); push_up(o); } void update(int o , int l , int r , int s , int t , int v) { if(l>=s && r<=t){ sum[o] += (ll)siz[o]*v; add[o] += v; return ; } define_m; push_down(o); if(m>=s) update(ls , l , m , s , t , v); if(m<t) update(rs , m+1 , r , s , t , v); push_up(o); } ll query(int o , int l , int r , int p) { if(l==r && l==p) return sum[o]; push_down(o); define_m; if(m>=p) return query(ls , l , m, p); else return query(rs , m+1 , r , p); } void updatePath(int u , int v , int change) { int top1 = top[u] , top2 = top[v]; while(top1!=top2){ if(dep[top1]<dep[top2]){ swap(top1 , top2); swap(u , v); } update(1 , 1 , n , id[top1] , id[u] , change); u = fa[top1]; top1 = top[u]; } if(dep[u]<dep[v]) swap(u , v); update(1 , 1 , n , id[v] , id[u] , change); } char str[4]; int main() { // freopen("in.txt" , "r" , stdin); while(~scanf("%d%d%d" ,&n , &m , &q)) { for(int i=1 ; i<=n ; i++) scanf("%d" , val+i); memset(first , -1 , sizeof(first)); k = 0; while(m--){ int u , v; scanf("%d%d" , &u , &v); add_edge(u,v); add_edge(v,u); } number = 0; dfs(1 , 0 , 1); id[1] = ++number; dfs1(1 , 0 , 1); // for(int i=1 ; i<=n ; i++) cout<<i<<" "<<son[i]<<" "<<id[i]<<endl; int tmp ; for(int i=1 ; i<=n ; i++) tmp[i]=val[i]; for(int i=1 ; i<=n ; i++) val[id[i]] = tmp[i]; build(1 , 1 , n); for(int i=0 ; i<q ; i++){ int s , t , v; scanf("%s" , str); if(str[0] == 'Q'){ scanf("%d" , &v); ll ans = query(1 , 1 , n , id[v]); printf("%d\n" , (int)ans); }else if(str[0]=='I'){ scanf("%d%d%d" , &s , &t , &v); updatePath(s , t , v); }else{ scanf("%d%d%d" , &s , &t , &v); updatePath(s , t , -v); } } } return 0; }
相关文章推荐
- LeetCode_Valid Parentheses
- zepto中使用swipe.js制作轮播图附swipeUp,swipeDown不起效果问题
- 2.2.2、容器的使用
- POJ 3020 Antenna Placement(二分图最小路径覆盖)
- Java synchronized详解
- 轻松解决mac改名之后,文件被清空的问题
- 三星手机上执行system()等函数失败
- Android音乐播放器汇总贴
- JSP运行原理
- 为什么要使用工作流引擎
- 【Developer Log】Log4j v2
- c++ string用法
- 使用ssh进行远程连接以及远程跳板以及scp远程上传下载文件说明
- Cocoa error 3840
- POJ 1014 Dividing
- KCore算法
- 2015-0827-osg学习历程2
- Fuse文件系统优化方案
- poj 1466 HDU 1068 Girls and Boys (最大独立集)
- cacti监控服务器