bzoj 3730

和上一题很像,而且这题直接给出了单点修改和区间查询,所以还是两棵线段树容斥即可

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
const int inf=0x3f3f3f3f;
struct Edge
{
    int next;
    int to;
}edge[200005];
struct Segtree
{
    int tot;
    int rot[100005];
    int lson[15000005];
    int rson[15000005];
    int v[15000005];
    void update(int &rt,int lq,int rq,int qx,int w)
    {
        if(!rt)rt=++tot;
        v[rt]+=w;
        if(lq==rq)return;
        int mid=(lq+rq)>>1;
        if(qx<=mid)update(lson[rt],lq,mid,qx,w);
        else update(rson[rt],mid+1,rq,qx,w);
    }
    int query(int rt,int lq,int rq,int ql,int qr)
    {
        if(!rt)return 0;
        if(lq>=ql&&rq<=qr)return v[rt];
        int mid=(lq+rq)>>1;
        int ret=0;
        if(ql<=mid)ret+=query(lson[rt],lq,mid,ql,qr);
        if(qr>mid)ret+=query(rson[rt],mid+1,rq,ql,qr);
        return ret;
    }
}tree1,tree2;
int head[100005];
int n,m;
int cnt=1;
int f[100005];
int dep[100005];
int siz[100005];
int maxp[100005];
int pre[100005];
bool vis[100005];
int v0[100005];
int huge[100005];
int son[100005];
int ttop[100005];
int rt,s;
inline int read()
{
    int f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void init()
{
    memset(head,-1,sizeof(head));
    cnt=1;
}
void add(int l,int r)
{
    edge[cnt].next=head[l];
    edge[cnt].to=r;
    head[l]=cnt++;
}
void dfs(int x,int fx)
{
    huge[x]=1;
    f[x]=fx;
    dep[x]=dep[fx]+1;
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
        int to=edge[i].to;
        if(to==fx)continue;
        dfs(to,x);
        huge[x]+=huge[to];
        if(huge[to]>huge[son[x]])son[x]=to;
    }
}
void redfs(int x,int tp)
{
    ttop[x]=tp;
    if(!son[x])return;
    redfs(son[x],tp);
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
        int to=edge[i].to;
        if(to==son[x]||to==f[x])continue;
        redfs(to,to);
    }
}
int LCA(int x,int y)
{
    while(ttop[x]!=ttop[y])
    {
        if(dep[ttop[x]]>dep[ttop[y]])swap(x,y);
        y=f[ttop[y]];
    }
    return dep[x]<dep[y]?x:y;
}
int get_dis(int x,int y)
{
    return dep[x]+dep[y]-2*dep[LCA(x,y)];
}
void get_rt(int x,int fa)
{
    siz[x]=1,maxp[x]=0;
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
        int to=edge[i].to;
        if(vis[to]||to==fa)continue;
        get_rt(to,x);
        siz[x]+=siz[to],maxp[x]=max(maxp[x],siz[to]);
    }
    maxp[x]=max(maxp[x],s-siz[x]);
    if(maxp[x]<maxp[rt])rt=x;
}
void solve(int x)
{
    vis[x]=1;
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
        int to=edge[i].to;
        if(vis[to])continue;
        rt=0,maxp[rt]=inf,s=siz[to];
        get_rt(to,0);
        pre[rt]=x;
        solve(rt);
    }
}
int main()
{
    n=read(),m=read();
    init();
    for(int i=1;i<=n;i++)v0[i]=read();
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y),add(y,x);
    }
    dfs(1,1);
    redfs(1,1);
    maxp[rt]=s=n;
    get_rt(1,0);
    solve(rt);
    for(int i=1;i<=n;i++)
    {
        int p=i,las=0;
        while(p)
        {
            int d=get_dis(p,i);
            tree1.update(tree1.rot[p],0,n,d,v0[i]);
            if(las)tree2.update(tree2.rot[las],0,n,d,v0[i]);
            las=p,p=pre[p];
        }
    }
    int lastans=0;
    while(m--)
    {
        int typ=read();
        if(typ)
        {
            int x=read()^lastans,temp=read()^lastans;
            int w=temp-v0[x];
            v0[x]=temp;
            int p=x,las=0;
            while(p)
            {
                int d=get_dis(x,p);
                tree1.update(tree1.rot[p],0,n,d,w);
                if(las)tree2.update(tree2.rot[las],0,n,d,w);
                las=p,p=pre[p];
            }
        }else
        {
            int x=read()^lastans,k=read()^lastans;
            int ans=0;
            int p=x,las=0;
            while(p)
            {
                int d=k-get_dis(x,p);
                if(d>=0)
                {
                    ans+=tree1.query(tree1.rot[p],0,n,0,d);
                    if(las)ans-=tree2.query(tree2.rot[las],0,n,0,d);
                }
                las=p,p=pre[p];
            }
            printf("%d\n",ans);
            lastans=ans;
        }
    }
    return 0;
}

 

posted @ 2019-04-30 15:35  lleozhang  Views(160)  Comments(0Edit  收藏  举报
levels of contents