您的位置:首页 > 其它

【bzoj4034】树上操作 树链剖分+线段树

2017-02-13 10:50 330 查看
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=4034

【题解】

用树剖来做的话,做法很显然,比模板题还简单。

不过,据说可以用dfs序搞一搞。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
#define FILE "read"
#define MAXN 100010
#define up(i,j,n) for(ll i=j;i<=n;++i)
#define dn(i,j,n) for(ll i=j;i>=n;--i)
#define cmax(a,b) a=max(a,b)
#define cmin(a,b) a=min(a,b)
namespace INIT{
char buf[1<<15],*fs,*ft;
inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline ll read(){
ll x=0,f=1; char ch=getc();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getc();}
return x*f;
}
}using namespace INIT;
struct node{ll y,next;}e[MAXN*2];
ll n,m,len,z,a[MAXN],Link[MAXN],size[MAXN],f[MAXN],w[MAXN],deep[MAXN],son[MAXN],top[MAXN],tr[MAXN*8],delta[MAXN*8];
void insert(ll x,ll y){e[++len].next=Link[x];Link[x]=len;e[len].y=y;}
void dfs(ll x){
size[x]=1; son[x]=0;
for(ll i=Link[x];i;i=e[i].next){
if(e[i].y==f[x]) continue;
f[e[i].y]=x; deep[e[i].y]=deep[x]+1;
dfs(e[i].y); size[x]+=size[e[i].y];
if(size[e[i].y]>size[son[x]]) son[x]=e[i].y;
}
}
void dfs(ll x,ll temp){
w[x]=++z; top[x]=temp;
if(son[x]) dfs(son[x],temp);
for(ll i=Link[x];i;i=e[i].next)
if(e[i].y!=f[x]&&e[i].y!=son[x]) dfs(e[i].y,e[i].y);
}
void pushdown(ll x,ll l,ll r){
ll delt=delta[x],mid=(l+r)>>1;
tr[x<<1]+=delt*(mid-l+1); tr[x<<1|1]+=delt*(r-mid);
delta[x<<1]+=delt; delta[x<<1|1]+=delt;
delta[x]=0;
}
void add(ll p,ll l,ll r,ll x,ll y,ll v){
pushdown(p,l,r);
if(x>r||y<l) return;
if(x<=l&&y>=r) {tr[p]+=v*(r-l+1); delta[p]+=v; return;}
ll mid=(l+r)>>1;
add(p<<1,l,mid,x,y,v); add(p<<1|1,mid+1,r,x,y,v);
tr[p]=tr[p<<1]+tr[p<<1|1];
}
ll find(ll p,ll l,ll r,ll x,ll y){
pushdown(p,l,r);
if(x>r||y<l) return 0;
if(x<=l&&y>=r) return tr[p];
ll mid=(l+r)>>1;
return find(p<<1,l,mid,x,y)+find(p<<1|1,mid+1,r,x,y);
}
ll solve(ll x){
ll ans=0;
while(x){
ans+=find(1,1,z,w[top[x]],w[x]);
x=f[top[x]];
}
return ans;
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
n=read(); m=read();
up(i,1,n) a[i]=read();
up(i,1,n-1) {ll x=read(),y=read(); insert(x,y); insert(y,x);}
dfs(1); dfs(1,1);
up(i,1,n) add(1,1,z,w[i],w[i],a[i]);
up(i,1,m){
ll opt=read();
if(opt==1) {ll x=read(),v=read(); add(1,1,z,w[x],w[x],v);}
else if(opt==2) {ll x=read(),v=read(); add(1,1,z,w[x],w[x]+size[x]-1,v);}
else {ll x=read(); printf("%lld\n",solve(x));}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: