2
19
2016
0

[BZOJ2836] 魔法树

因为一棵树的子树一定在dfs序上是连续的

所以直接修改就行了

bzoj 2836
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include<cstdio>
#include<algorithm>
using namespace std;
 
struct Edge{
int b,next;
}e[1000005];
 
struct SegTree{
int l,r;
long long tag,sum;
}tree[1000005];
 
int n,q,en,cnt,top[400005],id[400005],pre[400005],dep[400005],son[400005],h[400005],siz[400005],fa[400005];
 
void AddEdge(int sa,int sb){
e[++en].b=sb;
e[en].next=h[sa];
h[sa]=en;
}
 
void Pushdown(int root){
if(tree[root].tag){
    tree[root*2].tag+=tree[root].tag;
    tree[root*2].sum+=tree[root].tag*(tree[root*2].r-tree[root*2].l+1);
    tree[root*2+1].tag+=tree[root].tag;
    tree[root*2+1].sum+=tree[root].tag*(tree[root*2+1].r-tree[root*2+1].l+1);
    tree[root].tag=0;
}
}
 
void Pushup(int root){
tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
}
 
void Build(int root,int l,int r){
tree[root].l=l;
tree[root].r=r;
if(l==r){
    tree[root].sum=0;
    return;
}
int mid=(l+r)/2;
Build(root*2,l,mid);
Build(root*2+1,mid+1,r);
tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
}
 
void Add(int root,int l,int r,long long v){
if(tree[root].l>=l && tree[root].r<=r){
    tree[root].tag+=v;
    tree[root].sum+=v*(tree[root].r-tree[root].l+1);
    return;
}
Pushdown(root);
int mid=tree[root].l+tree[root].r>>1;
if(l<=mid)Add(root*2,l,r,v);
if(r>mid)Add(root*2+1,l,r,v);
Pushup(root);
}
 
long long Sum(int root,int l,int r){
if(tree[root].l>=l && tree[root].r<=r){
    return tree[root].sum;
}
Pushdown(root);
int mid=tree[root].l+tree[root].r>>1;
long long ans=0;
if(l<=mid)ans+=Sum(root*2,l,r);
if(r>mid)ans+=Sum(root*2+1,l,r);
return ans;
}
 
void dfs1(int u,int father,int deep){
fa[u]=father;
dep[u]=deep;
siz[u]=1;
son[u]=0;
for(int i=h[u];i;i=e[i].next){
    int v=e[i].b;
    if(v==father)continue;
    dfs1(v,u,deep+1);
    siz[u]+=siz[v];
    if(siz[v]>siz[son[u]]){
        son[u]=v;
    }
}
}
  
void dfs2(int u,int ux){
top[u]=ux;
id[u]=++cnt;
pre[cnt]=u;
if(son[u])dfs2(son[u],ux);
else return;
for(int i=h[u];i;i=e[i].next){
    int v=e[i].b;
    if(v!=son[u] && v!=fa[u]){dfs2(v,v);}
}
}
 
void AddLine(int u,int v,long long val){
int f1=top[u],f2=top[v];
while(f1!=f2){
    if(dep[f1]<dep[f2]){swap(u,v);swap(f1,f2);}
    Add(1,id[f1],id[u],val);
    u=fa[f1];
    f1=top[u];
}
if(dep[u]>dep[v])swap(u,v);
//printf("%d %d\n",id[u],id[v]);
Add(1,id[u],id[v],val);
}
 
int main(){
freopen("2836.in","r",stdin);
freopen("2836.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<n;i++){
    int u,v;
    scanf("%d %d",&u,&v);
    AddEdge(u+1,v+1);
    AddEdge(v+1,u+1);
}
Build(1,1,n);
dfs1(1,0,1);
dfs2(1,1);
scanf("%d",&q);
while(q--){
    int u,v;
    long long val;
    char s[3];
    scanf("%s",s);
    if(s[0]=='A'){
        scanf("%d %d %lld",&u,&v,&val);
        AddLine(u+1,v+1,val);
    }
    if(s[0]=='Q'){
        scanf("%d",&u);
        //printf("IS:%d %d %d\n",id[u+1],siz[u+1],u+1);
        printf("%lld\n",Sum(1,id[u+1],id[u+1]+siz[u+1]-1));
    }
}
return 0;
}
Category: BZOJ | Tags: OI bzoj | Read Count: 520

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com