zoukankan      html  css  js  c++  java
  • 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
    ",ans);
                lastans=ans;
            }
        }
        return 0;
    }
  • 相关阅读:
    【python】 time模块和datetime模块详解 【转】
    【python 】装饰器 (多个参数的函数,带参数的装饰器)【转】
    从测试角度对测试驱动开发的思考【转】
    mysql性能优化-慢查询分析、优化索引和配置【转】
    【python 】Requests 库学习笔记
    二本院校计算机专业考研上岸985
    mysql创建触发器
    pat 1134 Vertex Cover (25分) 超时问题
    数据库三级封锁协议简述
    pat 1139 First Contact (30分) 题目详解
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10796322.html
Copyright © 2011-2022 走看看