[HAOI2015]树上操作

bzoj 4034
注意longlong 注意数组大小
辣鸡线段树大小!!!QAQ

#include
#include
#include
#include
#define N 100002 
#define LL long long
#define ls x<<1
#define rs x<<1|1
using namespace std;
int n,m,tot=0,df=0;
int head[5*N],to[5*N],nxt[5*N],dfn[N];
int sz[N],tp[N],son[N],de[N],fa[N],ed[N];
LL tree[8*N],v[N],lazy[8*N];
void link(int x,int y)
{
    nxt[++tot]=head[x];
    to[tot]=y;
    head[x]=tot;
}
void dfs(int x)
{
    sz[x]=1;
    for (int i=head[x];i;i=nxt[i])
    {
        int t=to[i];
        if (t==fa[x]) continue;
        de[t]=de[x]+1;
        fa[t]=x;
        dfs(t);
        sz[x]+=sz[t];
        if (sz[t]>sz[son[x]]) son[x]=t;
    }
}
void dfs1(int x,int top)
{
    dfn[x]=++df,tp[x]=top;
    if (son[x]) dfs1(son[x],top);
    for (int i=head[x];i;i=nxt[i])
    {
        int t=to[i];
        if (t==fa[x]||t==son[x]) continue;
        dfs1(t,t);
    }
    ed[x]=df;
}
void down (int x,int l,int r)
{
    int mid=(r+l)>>1;
    tree[ls]+=lazy[x]*(mid-l+1);
    tree[rs]+=lazy[x]*(r-mid);
    lazy[ls]+=lazy[x];
    lazy[rs]+=lazy[x];
    lazy[x]=0;
}
void update(int x,int l,int r,int ll,int rr,LL w)
{
    if (l!=r) down(x,l,r);
    if (ll<=l&&r<=rr)
    {
        tree[x]+=w*(r-l+1);
        lazy[x]=w;
        return ;
    }
    int mid=(l+r)>>1;
    if (ll<=mid) update(ls,l,mid,ll,rr,w);
    if (rr>mid) update(rs,mid+1,r,ll,rr,w);
    tree[x]=tree[ls]+tree[rs];
}
LL query(int x,int l,int r,int ll,int rr)
{
    if (l!=r) down(x,l,r);
    if (ll<=l&&r<=rr) return tree[x];
    int mid=(l+r)>>1;
    LL ans=0;
    if (ll<=mid) ans+=query(ls,l,mid,ll,rr);
    if (rr>mid) ans+=query(rs,mid+1,r,ll,rr);
    return ans;
}
LL lca(int x)
{
    LL ans=0;
    while (tp[x]!=1)
    {
        ans+=query(1,1,n,dfn[tp[x]],dfn[x]);
        x=fa[tp[x]];
    }
    ans+=query(1,1,n,1,dfn[x]);
    return ans;
}
int main()
{
    scanf ("%d%d",&n,&m);
    for (int i=1;i<=n;++i) scanf ("%lld",&v[i]);
    for (int i=1;iint x,y;
        scanf ("%d%d",&x,&y);
        link(x,y);
        link(y,x);
    }
    de[1]=1;
    dfs(1),dfs1(1,1);
    for (int i=1;i<=n;++i) update(1,1,n,dfn[i],dfn[i],v[i]);
    for (int i=1;i<=m;++i)
    {
        //cout<1,1,n,dfn[2],dfn[2])<<"**"<int fl=1;
        scanf ("%d",&fl);
        if (fl==1)
        {
            int x,a;
            scanf ("%d%d",&x,&a);
            update(1,1,n,dfn[x],dfn[x],a);
        }
        if (fl==2)
        {
            int x,a;
            scanf ("%d%d",&x,&a);
            update(1,1,n,dfn[x],ed[x],a);
        }
        if (fl==3)
        {
            int x;
            scanf ("%d",&x);
            printf("%lld\n",lca(x));
        }
    }
    return 0;
}

我真是太愚蠢啦qaq

你可能感兴趣的:(树)