题目
http://www.lydsy.com/JudgeOnline/problem.php?id=4034
题解
今天上午NOIP模拟赛死机了两次,结果爆炸120分,被高一的ftm大牛和hzw大牛150碾压了,感觉很不爽,于是来怒刷水题。
树链剖分+线段树。
代码
//树链剖分
#include <cstdio>
#include <algorithm>
#define ll long long
#define maxn 200010
using namespace std;
ll N, M, head[maxn], to[maxn], tmp[maxn], next[maxn], val[maxn], tid[maxn], fa[maxn],
top[maxn], size[maxn], son[maxn], deep[maxn], tot, tim, segtot, l[maxn], r[maxn];
void adde(ll a, ll b){to[++tot]=b;next[tot]=head[a];head[a]=tot;}
struct segtree
{
ll l, r, sum, tag;
segtree *lch, *rch;
}node[maxn], *root;
void pushdown(segtree *p)
{
if(p->tag)
{
p->sum+=(p->r-p->l+1)*p->tag;
if(p->lch)p->lch->tag+=p->tag,p->rch->tag+=p->tag;
p->tag=0;
}
}
void update(segtree *p)
{
if(p->lch==0)return;
pushdown(p->lch),pushdown(p->rch);
p->sum=p->lch->sum+p->rch->sum;
}
void build(segtree *p, ll l, ll r)
{
ll mid=(l+r)>>1;
p->l=l,p->r=r;
if(l==r){p->sum=val[l];return;}
build(p->lch=node+ ++segtot,l,mid);
build(p->rch=node+ ++segtot,mid+1,r);
p->sum=p->lch->sum+p->rch->sum;
}
ll segsum(segtree *p, ll l, ll r)
{
pushdown(p);
ll mid=(p->l+p->r)>>1, ans=0;
if(l<=p->l and r>=p->r)return p->sum;
if(l<=mid)ans+=segsum(p->lch,l,r);
if(r>mid)ans+=segsum(p->rch,l,r);
return ans;
}
void segtag(segtree *p, ll l, ll r, ll tag)
{
ll mid=(p->l+p->r)>>1;
if(l<=p->l and r>=p->r){p->tag+=tag;return;}
if(l<=mid)segtag(p->lch,l,r,tag);
if(r>mid)segtag(p->rch,l,r,tag);
update(p);
}
void dfs1(ll pos)
{
ll p, v;
size[pos]=1;
son[pos]=-1;
for(p=head[pos];p;p=next[p])
{
if((v=to[p])==fa[pos])continue;
fa[v]=pos;
deep[v]=deep[pos]+1;
dfs1(v);
if(son[pos]==-1 or size[v]>size[son[pos]])son[pos]=v;
size[pos]+=size[v];
}
}
void dfs2(ll pos, ll tp)
{
ll p, v;
tid[pos]=++tim;
top[pos]=tp;
l[pos]=tim;
if(son[pos]!=-1)dfs2(son[pos],tp);
for(p=head[pos];p;p=next[p])
{
if((v=to[p])==fa[pos] or v==son[pos])continue;
dfs2(v,v);
}
r[pos]=tim;
}
ll calcsum(ll x)
{
ll tx=top[x], ans=0;
while(tx!=1)
{
ans+=segsum(root,tid[tx],tid[x]);
x=fa[tx];tx=top[x];
}
return ans+segsum(root,1,tid[x]);
}
void init()
{
ll i, a, b;
scanf("%lld%lld",&N,&M);
for(i=1;i<=N;i++)scanf("%lld",tmp+i);
for(i=1;i<N;i++)scanf("%lld%lld",&a,&b),adde(a,b),adde(b,a);
dfs1(1);
dfs2(1,1);
for(i=1;i<=N;i++)val[tid[i]]=tmp[i];
build(root=node+ ++segtot,1,tim);
}
void solve()
{
ll i, x, a, type;
for(i=1;i<=M;i++)
{
scanf("%lld%lld",&type,&x);
if(type==1)scanf("%lld",&a),segtag(root,tid[x],tid[x],a);
if(type==2)scanf("%lld",&a),segtag(root,l[x],r[x],a);
if(type==3)printf("%lld\n",calcsum(x));
}
}
int main()
{
init();
solve();
return 0;
}