• BZOJ4372: 烁烁的游戏


    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不一定为正整数,因为烁烁可能把皮皮鼠吓傻了。

     
    裸的动态树分治,和震波很像啊(时限宽松多了)。
    套个支持区间增加的线段树就行了。
    数组开小结果RE2次(TAT)。
    前面10s的太强了。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=200010;
    const int maxnode=20000010;
    int n,m,first[maxn],next[maxn<<1],to[maxn<<1],e;
    void AddEdge(int u,int v) {
        to[++e]=v;next[e]=first[u];first[u]=e;
        to[++e]=u;next[e]=first[v];first[v]=e;
    }
    int val[maxn],mn[maxn<<1][20],Log[maxn<<1],dep[maxn],pos[maxn],cnt;
    void dfs(int x,int fa) {
        dep[x]=dep[fa]+1;pos[x]=++cnt;mn[cnt][0]=dep[x];
        ren if(to[i]!=fa) dfs(to[i],x),mn[++cnt][0]=dep[x];
    }
    void init() {
        Log[0]=-1;
        rep(i,1,cnt) Log[i]=Log[i>>1]+1;
        for(int j=1;(1<<j)<=cnt;j++)
            for(int i=1;i+(1<<j)-1<=cnt;i++)
                mn[i][j]=min(mn[i][j-1],mn[i+(1<<j-1)][j-1]);
    }
    int dist(int x,int y) {
        int k,ans=dep[x]+dep[y];
        x=pos[x];y=pos[y];if(x>y) swap(x,y);k=Log[y-x+1];
        return ans-2*min(mn[x][k],mn[y-(1<<k)+1][k]);
    }
    int vis[maxn],f[maxn],s[maxn],root,size;
    void getroot(int x,int fa) {
        int maxs=0;s[x]=1;
        ren if(to[i]!=fa&&!vis[to[i]]) {
            getroot(to[i],x);s[x]+=s[to[i]];
            maxs=max(maxs,s[to[i]]);
        }
        f[x]=max(maxs,size-s[x]);
        if(f[root]>f[x]) root=x;
    }
    int fa[maxn];
    void build(int x) {
        vis[x]=1;
        ren if(!vis[to[i]]) {
            size=f[0]=s[to[i]];getroot(to[i],root=0);
            fa[root]=x;build(root);
        }
    }
    int ls[maxnode],rs[maxnode],addv[maxnode],ToT;
    int root1[maxn],root2[maxn];
    void update(int& o,int l,int r,int ql,int qr,int v) {
        if(!o) o=++ToT;
        if(ql<=l&&r<=qr) addv[o]+=v;
        else {
            int mid=l+r>>1;
            if(ql<=mid) update(ls[o],l,mid,ql,qr,v);
            if(qr>mid) update(rs[o],mid+1,r,ql,qr,v);
        }
    }
    int query(int& o,int l,int r,int pos,int cur) {
        cur+=addv[o];
        if(!o||pos<0||l==r) return cur;
        int mid=l+r>>1;
        if(pos<=mid) return query(ls[o],l,mid,pos,cur);
        return query(rs[o],mid+1,r,pos,cur);
    }
    void update(int x,int w,int v) {
        update(root1[x],0,n,0,w,v);
        for(int i=x;fa[i];i=fa[i]) {
            int D=dist(x,fa[i]);
            if(w>=D) {
                update(root1[fa[i]],0,n,0,w-D,v);
                update(root2[i],0,n,0,w-D,v);
            }
        }
    }
    int query(int x) {
        int res=query(root1[x],0,n,0,0);
        for(int i=x;fa[i];i=fa[i]) {
            int D=dist(x,fa[i]);
            res+=query(root1[fa[i]],0,n,D,0)-query(root2[i],0,n,D,0);
        }
        return res;
    }
    int main() {
        n=read();m=read();
        rep(i,2,n) AddEdge(read(),read());
        dfs(1,0);init();
        f[0]=size=n;getroot(1,root=0);
        build(root);
        while(m--) {
            char cmd[2];
            scanf("%s",cmd);
            if(cmd[0]=='Q') printf("%d
    ",query(read()));
            else {
                int x=read(),w=read(),v=read();
                update(x,w,v);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    绕过校园网认证实现免费上网【三端】
    Java多线程下载器FileDownloader(支持断点续传、代理等功能)
    Java实现命令行中的进度条功能
    记一次基于Cloudflare服务的爬虫
    如何修改npm包源码后,重新npm包的时候能是修改后的版本
    将html片段的文本内容取出来
    阿里云的oss的文件资源链接强制下载
    常用正则记录
    flvjs的unload(),detachMediaElement(),destroy()报错,undefined,not a function解决方案
    微信扫码登陆,qq登陆,微博登陆等第三方登陆成功后返回原来的页面并进行跳转
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5090038.html
Copyright © 2020-2023  润新知