赛后补题: 树链剖分套区间更新线段树 注意lca的求法
官方题解:http://codeforces.com/blog/entry/57223
code:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<vector>
#include<string>
#include<queue>
using namespace std;
const int maxn = 100055;
const int mod = 1e9+7;
typedef long long ll;
#define lson rt<<1
#define rson rt<<1|1
#define inf 1<<30
int root,sum,num;
int pos[maxn];
int top[maxn];
int Size[maxn];
int p[maxn];
int id[maxn];
int son[maxn];
int d[maxn];
ll val[maxn];
int la[maxn];
vector<int> G[maxn];
struct node{
int l,r;
ll val;
ll lazy;
}rmq[maxn<<2];
void init(){
memset(son,-1,sizeof(son));
memset(p,-1,sizeof(p));
root=1;
}
void dfs1(int u,int fa,int step){
d[u]=step;
p[u]=fa;
Size[u]=1;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v==fa) continue;
dfs1(v,u,step+1);
Size[u]+=Size[v];
if(son[u]==-1||Size[v]>Size[son[u]]) son[u]=v;
}
}
void dfs2(int u,int tp){
// cout<<u<<' '<<tp<<endl;
top[u]=tp;
id[u]=la[u]=++num;
pos[id[u]]=u;
if(son[u]==-1) return ;
dfs2(son[u],tp);
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v!=son[u]&&v!=p[u]){
dfs2(v,v);
}
}
la[u]=num;
}
int lca(int u,int v){
// cout<<u<<' '<<v<<endl;
while(top[u]!=top[v]){
if(d[top[u]]<d[top[v]]) swap(u,v);
u=p[top[u]];
// cout<<u<<' '<<v<<endl;
}
return d[u]<d[v]?u:v;
}
int LCA(int u,int v){
int a=lca(u,v);
int b=lca(root,u);
int c=lca(root,v);
if(d[a]<d[b]) swap(a,b);
if(d[a]<d[c]) swap(a,c);
return a;
}
int nearlca(int u,int v){
if(d[u]>d[v]) swap(u,v);
if(top[u]==top[v]) return pos[id[u]+1];
while(top[u]!=top[v]){
if(d[top[u]]>d[top[v]]) swap(u,v);
if(p[top[v]]==u) break;
else v=p[top[v]];
}
if(top[u]==top[v]) return pos[id[u]+1];
else return top[v];
}
void Pushup(int rt){
rmq[rt].val=rmq[lson].val+rmq[rson].val;
}
void Pushdown(int rt){
int l=rmq[rt].l;
int r=rmq[rt].r;
int m=(l+r)>>1;
if(rmq[rt].lazy!=0){
ll c=rmq[rt].lazy;
rmq[lson].lazy+=c;
rmq[rson].lazy+=c;
rmq[lson].val+=(ll)(m-l+1)*c;
rmq[rson].val+=(ll)(r-m)*c;
rmq[rt].lazy=0;
}
}
void build(int l,int r,int rt){
rmq[rt].l=l;
rmq[rt].r=r;
rmq[rt].lazy=0;
if(l==r){
rmq[rt].val=val[pos[l]];
return;
}
int m=(l+r)>>1;
build(l,m,lson);
build(m+1,r,rson);
Pushup(rt);
}
void update(int rt,int L,int R,int c){
int l=rmq[rt].l;
int r=rmq[rt].r;
if(L<=l&&r<=R){
rmq[rt].val+=(ll)(r-l+1)*c;
rmq[rt].lazy+=c;
return ;
}
Pushdown(rt);
int m=(l+r)>>1;
if(L<=m) update(lson,L,R,c);
if(m<R) update(rson,L,R,c);
Pushup(rt);
}
ll query(int rt,int L,int R){
int l=rmq[rt].l;
int r=rmq[rt].r;
if(L<=l&&r<=R) return rmq[rt].val;
Pushdown(rt);
int m=(l+r)>>1;
ll ret=0;
if(L<=m) ret+=query(lson,L,R);
if(m<R) ret+=query(rson,L,R);
return ret;
}
void add_edge(int u,int v){
G[u].push_back(v);
G[v].push_back(u);
}
ll Query(int x){
return query(1,id[x],la[x]);
}
void Update(int x,int c){
update(1,id[x],la[x],c);
}
bool ini(int x,int y){
if(id[x]>=id[y]&&id[x]<=la[y]) return true;
return false;
}
int main(){
// freopen("in.txt","r",stdin);
init();
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
cin>>val[i];
}
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
}
dfs1(1,-1,0);
dfs2(1,1);
build(1,num,1);
/*
for(int i=1;i<=n;i++){
cout<<i<<' '<<id[i]<<' '<<la[i]<<endl;
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++){
cout<<i<<' '<<j<<' '<<nearlca(i,j)<<endl;
}
*/
while(q--){
int k;
scanf("%d",&k);
if(k==1){
int v;
scanf("%d",&v);
root=v;
}else if(k==2){
int u,v,x;
scanf("%d%d%d",&u,&v,&x);
int in_cnt=0;
int rt;
if(ini(u,root)) in_cnt++;
if(ini(v,root)) in_cnt++;
if(in_cnt==1) rt=root;
else if(in_cnt==2) rt=lca(u,v);
else rt=LCA(u,v);
if(rt==root){
Update(1,x);
}else if(ini(rt,root)){
Update(rt,x);
}else if(ini(root,rt)){
Update(1,x);
int y=nearlca(root,rt);
Update(y,-x);
}else {
Update(rt,x);
}
}else if(k==3){
int v;
scanf("%d",&v);
ll ans;
if(v==root){
ans=Query(1);
}else if(ini(v,root)){
ans=Query(v);
}else if(ini(root,v)){
ans=Query(1);
int x=nearlca(root,v);
ans-=Query(x);
}else {
ans=Query(v);
}
cout<<ans<<endl;
}
}
return 0;
}