您的位置:首页 > 其它

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的权值

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: