[HAOI2015]树上操作(树链剖分)
原题
Solution
直接很简单的树链剖分然后搞一个线段树维护一下就好了?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<queue>
#define ll long long
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
using namespace std;
inline int gi(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-f;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
inline ll gl(){
ll sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-f;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
const int maxn=500010;
ll old[maxn];int to[maxn<<1],nxt[maxn<<1],front[maxn],cnt;ll w[maxn];
int siz[maxn],fa[maxn],dep[maxn],son[maxn],top[maxn],b[maxn],n;
struct node{
int l,r;ll add,val;
}tree[maxn<<4];
void Add(int u,int v){
to[++cnt]=v;nxt[cnt]=front[u];front[u]=cnt;
}
void dfs1(int u,int f){
siz[u]=1;fa[u]=f;dep[u]=dep[f]+1;
for(int i=front[u];i;i=nxt[i]){
int v=to[i];
if(v!=fa[u]){
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
}
void dfs2(int u,int tp){
top[u]=tp;b[u]=++cnt;w[cnt]=old[u];
if(!son[u])return;
dfs2(son[u],tp);
for(int i=front[u];i;i=nxt[i]){
int v=to[i];
if(v!=son[u] && v!=fa[u])dfs2(v,v);
}
}
void pushup(int o){
tree[o].val=tree[o<<1].val+tree[o<<1|1].val;
}
void build(int o,int l,int r){
tree[o].l=l;tree[o].r=r;tree[o].add=0;
if(l==r){
tree[o].val=w[l];
return;
}
int mid=(l+r)>>1;
build(o<<1,l,mid);build(o<<1|1,mid+1,r);
pushup(o);
}
void pushdown(int o){
if(tree[o].add){
tree[o<<1].add+=tree[o].add;
tree[o<<1|1].add+=tree[o].add;
tree[o<<1].val+=tree[o].add*(tree[o<<1].r-tree[o<<1].l+1);
tree[o<<1|1].val+=tree[o].add*(tree[o<<1|1].r-tree[o<<1|1].l+1);
tree[o].add=0;
}
}
void update(int o,int l,int r,int posl,int posr,ll k){
if(posl<=l && r<=posr){
tree[o].val+=k*(r-l+1);tree[o].add+=k;
return;
}
pushdown(o);
int mid=(l+r)>>1;
if(mid>=posr)update(o<<1,l,mid,posl,posr,k);
else if(mid<posl)update(o<<1|1,mid+1,r,posl,posr,k);
else{
update(o<<1,l,mid,posl,mid,k);
update(o<<1|1,mid+1,r,mid+1,posr,k);
}
pushup(o);
}
ll query(int o,int l,int r,int posl,int posr){
if(posl<=l && r<=posr)return tree[o].val;
pushdown(o);
int mid=(l+r)>>1;
if(mid>=posr)return query(o<<1,l,mid,posl,posr);
else if(mid<posl)return query(o<<1|1,mid+1,r,posl,posr);
return query(o<<1,l,mid,posl,mid)+query(o<<1|1,mid+1,r,mid+1,posr);
}
ll Query(int u,int v){
ll ans=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
ans+=query(1,1,n,b[top[u]],b[u]);u=fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);
return ans+query(1,1,n,b[u],b[v]);
}
int main(){
int i,j,m,k;
n=gi();m=gi();
for(i=1;i<=n;i++)old[i]=gi();
for(i=1;i<n;i++){
int u=gi(),v=gi();
Add(u,v);Add(v,u);
}
cnt=0;
dfs1(1,1);dfs2(1,1);
build(1,1,n);
while(m--){
int x,a,opt;cin>>opt>>x;
if(opt==1){
cin>>a;
update(1,1,n,b[x],b[x],a);
}
else if(opt==2){
cin>>a;
update(1,1,n,b[x],b[x]+siz[x]-1,a);
}
else printf("%lld\n",Query(1,x));
}
return 0;
}