JZYZOJ1539[haoi2015]T2 树链剖分

时间:2023-03-09 21:54:28
JZYZOJ1539[haoi2015]T2 树链剖分

http://172.20.6.3/Problem_Show.asp?id=1539

在学校的OJ又写了一次,RE了好多次,原来haoi的时候这道题需要开栈+快读,裸数据结构30分,加上快读50分。
oi考试的时候原来不能汇编开栈,只能写手工栈orz(递归变循环那种),学长说当时省选最高分50,本来以为很简单的题没想到这么套路。

代码

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define lc x*2
#define rc x*2+1
const int maxn=;
int n,m;
long long a[maxn]={};
struct nod{
int y,next;
}e[maxn*];
int head[maxn]={},tot=;
long long fa[maxn]={},dep[maxn]={},siz[maxn]={};
long long kid[maxn]={},top[maxn]={},val[maxn]={};
struct seg{
long long l,r,v,w,siz;
seg(){l=r=v=w=siz=;}
}t[maxn*];
void init(long long x,long long y){
e[++tot].y=y;e[tot].next=head[x];head[x]=tot;
}
int build1(int x,int pa){
int y,hug=,si,tsn=;fa[x]=pa;
for(int i=head[x];i;i=e[i].next){
y=e[i].y;
if(y==pa)continue;
si=build1(y,x);tsn+=si;
if(si>hug)hug=si,kid[x]=y;
}return siz[x]=tsn;
}
void build2(int x,int pa){
int y;dep[x]=++tot;top[x]=pa;
val[dep[x]]=a[x];
if(kid[x])build2(kid[x],pa);
for(int i=head[x];i;i=e[i].next){
y=e[i].y;
if(y==kid[x]||y==fa[x])continue;
build2(y,y);
}
}
void pushup(int x){
if(t[x].siz>)t[x].v=t[lc].v+t[rc].v;
t[x].v+=t[x].w*t[x].siz;
}
void build(int x,int l,int r){
t[x].r=r;t[x].l=l;t[x].siz=r-l+;
if(l==r){t[x].v=val[l];return;}
int mid=(l+r)/;
build(lc,l,mid);
build(rc,mid+,r);
pushup(x);
}
void add(int x,int l,int r,long long w){
if(l<=t[x].l&&t[x].r<=r){
if(t[x].l==t[x].r)t[x].v+=w;
else t[x].w+=w;pushup(x);
return;
}
int mid=(t[x].l+t[x].r)/;
if(l<=mid)add(lc,l,r,w);
if(r>mid)add(rc,l,r,w);
pushup(x);
}
long long sum(int x,int l,int r,long long w){
if(l<=t[x].l&&t[x].r<=r){
return t[x].v+t[x].siz*w;
}
int mid=(t[x].l+t[x].r)/;long long ans=;
if(l<=mid)ans+=sum(lc,l,r,w+t[x].w);
if(r>mid)ans+=sum(rc,l,r,w+t[x].w);
return ans;
}
long long doit(int x){
int a=top[x];long long ans=;
while(a!=){
ans+=sum(,dep[a],dep[x],);
x=fa[a];a=top[x];
}
ans+=sum(,dep[a],dep[x],);
return ans;
}
long long read(){
char ch=getchar();long long x=,f=;
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x*=;x+=ch-'';ch=getchar();}
return x*f;
}
int main(){
//freopen("wtf.in","r",stdin);
int size = << ; // 256MB
char *p = (char*)malloc(size) + size;
__asm__("movl %0, %%esp\n" :: "r"(p));
n=read();m=read();int x,y,v;
for(int i=;i<=n;i++)a[i]=read();
for(int i=;i<n;i++){x=read();y=read();init(x,y);init(y,x);}
tot=;build1(,);build2(,);
build(,,n);
for(int i=;i<=m;i++){
scanf("%d",&v);
if(v==){
scanf("%d%d",&x,&y);
add(,dep[x],dep[x],y);
}
else if(v==){
scanf("%d%d",&x,&y);
add(,dep[x],dep[x]+siz[x]-,y);
}
else{
scanf("%d",&x);
printf("%I64d\n",doit(x));
}
}
return ;
}