• [BZOJ]4372: 烁烁的游戏


    Time Limit: 30 Sec  Memory Limit: 512 MB

    Description

      背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠。
      题意:
      给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠。
      烁烁他每次会跳到一个节点u,把周围与他距离不超过d的节点各吸引出w只皮皮鼠。皮皮鼠会被烁烁吸引,所以会一直待在节点上不动。
      烁烁很好奇,在当前时刻,节点u有多少个他的好朋友---皮皮鼠。
      大意:
      给一颗n个节点的树,边权均为1,初始点权均为0,m次操作:
      Q x:询问x的点权。
      M x d w:将树上与节点x距离不超过d的节点的点权均加上w。

    Input

      第一行两个正整数:n,m
      接下来的n-1行,每行三个正整数u,v,代表u,v之间有一条边。
      接下来的m行,每行给出上述两种操作中的一种。

    Output

      对于每个Q操作,输出当前x节点的皮皮鼠数量。

    Sample Input

      7 6
      1 2
      1 4
      1 5
      2 3
      2 7
      5 6
      M 1 1 2
      Q 5
      M 2 2 3
      Q 3
      M 1 2 1
      Q 2

    Sample Output

      2
      3
      6

    HINT

      数据范围:
      n,m<=10^5,|w|<=10^4
      注意:w不一定为正整数,因为烁烁可能把皮皮鼠吓傻了。

    Solution

      动态点分治。先建出点分治的分治结构,修改一个点的时候,对于每一层该点所在的分治结构,开一个线段树在d减该点到重心距离(即到其他子树的最远距离)的位置加上w,查询同样对每一层的线段树查询大等于该点到重心距离的权值和,为了避免统计到自己子树内的信息,每一层分治结构的每个大的子树都再开一个线段树存储子树内信息。总复杂度$O(nlog^{2}n)$。

    Code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x,f=1;char c;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=0;
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=x*10+c-'0';
        return f?x:-x;
    }
    #define MN 100000
    #define K 20
    #define ND 30000000
    struct edge{int nx,t;}e[MN*2+5];
    int h[MN+5],en,sz,rt,rts,u[MN+5],s[MN+5];
    int fa[MN+5],dep[MN+5],t1[MN+5],t2[K][MN+5],tn,d[K][MN+5];
    struct node{int l,r,s;}t[ND+5];
    inline void ins(int x,int y)
    {
        e[++en]=(edge){h[x],y};h[x]=en;
        e[++en]=(edge){h[y],x};h[y]=en;
    }
    int query(int k,int l,int r,int ql,int qr)
    {
        if(l==ql&&r==qr)return t[k].s;
        int mid=l+r>>1;
        if(qr<=mid)return query(t[k].l,l,mid,ql,qr);
        if(ql>mid)return query(t[k].r,mid+1,r,ql,qr);
        return query(t[k].l,l,mid,ql,mid)+query(t[k].r,mid+1,r,mid+1,qr);
    }
    void add(int&k,int l,int r,int x,int ad)
    {
        if(!k)k=++tn;
        if(l==r){t[k].s+=ad;return;}
        int mid=l+r>>1;
        if(x<=mid)add(t[k].l,l,mid,x,ad);
        else add(t[k].r,mid+1,r,x,ad);
        t[k].s=t[t[k].l].s+t[t[k].r].s;
    }
    void getrt(int x,int fa)
    {
        int mx=0;
        s[x]=1;
        for(int i=h[x];i;i=e[i].nx)if(e[i].t!=fa&&!u[e[i].t])
            getrt(e[i].t,x),s[x]+=s[e[i].t],mx=max(mx,s[e[i].t]);
        mx=max(mx,sz-s[x]);
        if(mx<rts)rts=mx,rt=x;
    }
    void dfs(int x,int fa,int dep)
    {
        s[x]=1;d[dep][x]=d[dep][fa]+1;
        for(int i=h[x];i;i=e[i].nx)if(e[i].t!=fa&&!u[e[i].t])
            t2[dep][e[i].t]=t2[dep][x],dfs(e[i].t,x,dep),s[x]+=s[e[i].t];
    }
    void solve(int x)
    {
        int i;u[x]=1;
        for(i=h[x];i;i=e[i].nx)if(!u[e[i].t])
            t2[dep[x]][e[i].t]=++tn,dfs(e[i].t,x,dep[x]);
        for(i=h[x];i;i=e[i].nx)if(!u[e[i].t])
            sz=rts=s[e[i].t],getrt(e[i].t,x),
            fa[rt]=x,dep[rt]=dep[x]+1,solve(rt);
    }
    int main()
    {
        int n,m,i,x,y,w;char s[5];
        n=read();m=read();
        for(i=1;i<n;++i)ins(read(),read());
        sz=rts=n;getrt(1,0);solve(rt);
        while(m--)
        {
            scanf("%s",s);
            if(s[0]=='M')
            {
                x=read();y=read();w=read();
                for(i=x;i;i=fa[i])if(y>=d[dep[i]][x])
                {
                    add(t1[i],0,MN,y-d[dep[i]][x],w);
                    if(t2[dep[i]][x])add(t2[dep[i]][x],0,MN,y-d[dep[i]][x],w);
                }
            }
            else
            {
                x=read();w=0;
                for(i=x;i;i=fa[i])
                    w+=query(t1[i],0,MN,d[dep[i]][x],MN)-query(t2[dep[i]][x],0,MN,d[dep[i]][x],MN);
                printf("%d
    ",w);
            }
        }
    }
  • 相关阅读:
    pytest 失败重试
    mysql 增删改查
    jenkins分布式启动slave发现ip不对应实际ip
    测试架构师必读:编码规范、开发技巧、架构画图
    mysql limit和offset用法
    pytest 使用fixture给测试函数传参
    mysql union和union all
    pytest setup和teardown用法
    pytest的Hook函数详解
    pytest 用例依赖
  • 原文地址:https://www.cnblogs.com/ditoly/p/BZOJ4372.html
Copyright © 2020-2023  润新知