zoukankan      html  css  js  c++  java
  • CF725G

    首先我们考虑事件发生的真正的先后顺序

    我们考虑在某一个点$f$的子树内有两点$i$,$j$先后在$t_{i}$,$t_{j}$两个时间向上发送信息

    那么两者谁会先传到$f$呢?

    推个小式子:设$i$先到达$f$,那么一定要满足的条件是$dep_{i}-dep_{f}+t_{i}$<$dep_{j}-dep_{f}+t_{j}$

    发现这个不等式与$f$无关,因此可以推出一般规律:

    一个事件在另一个事件之前产生影响的条件是$dep_{i}+t_{i}<dep_{j}+t_{j}$

    因此我们按这一标准对所有询问排序,这样只需从前向后处理即可

    接下来我们考虑一个点向上最多能跳到哪:

    首先不难发现:如果一个点$f$正在等待发源于点$p$的信息的回复,那么这个$f$将等到$2dep_{p}+t_{p}-(dep_{p}-dep_{f})$,也就是说在这个时间点之前$f$都将在等待$p$的信息的回复(这里我们假设$i$的信息传递到了根,否则的话需要去掉实际到达的点的深度)

    假设我们有一个来自于$i$的信息需要经过$f$,那么我们只需比较这条信息到达$f$的时间点与上面那个时间点的关系就能知道是否可以经过$f$了

    也即当$dep_{i}-dep_{f}+t_{i}>2dep_{p}+t_{p}-(dep_{p}-dep_{f})$时,$i$的信息可以经过$f$

    可是这个东西乱七八糟的怎么搞嘛!

    整理一下,能够得到:$dep_{i}+t_{i}>dep_{p}+t_{p}+2dep_{f}$

    $dep_{f}$始终不变,$dep_{p}+t_{p}$只与$p$有关,用线段树维护树剖即可,查询时在链上二分右侧那堆东西的最大值

    贴代码:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <vector>
    #define rt1 rt<<1
    #define rt2 (rt<<1)|1
    using namespace std;
    struct Seg_tree
    {
        int maxv,ori,lazy;
    }tree[800005];
    int dep[200005],nnum[200005],onum[200005],ttop[200005],f[200005],siz[200005],son[200005];
    struct Ques
    {
        int p,t,num;
        friend bool operator < (Ques a,Ques b)
        {
            return dep[a.p]+a.t==dep[b.p]+b.t?a.p<b.p:dep[a.p]+a.t<dep[b.p]+b.t;
        }
    }q[200005];
    vector <int> v[200005];
    int ret[200005];
    int n,m,tot;
    void dfs(int x,int fx)
    {
        siz[x]=1,dep[x]=dep[fx]+1,f[x]=fx;
        for(int i=0;i<v[x].size();i++)
        {
            int to=v[x][i];
            if(to==fx)continue;
            dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[to]>siz[son[x]])?to:son[x];
        }
    }
    void redfs(int x,int fx,int topx)
    {
        ttop[x]=topx,nnum[x]=++tot,onum[tot]=x;
        if(son[x])redfs(son[x],x,topx);
        for(int i=0;i<v[x].size();i++)
        {
            int to=v[x][i];
            if(to==fx||to==son[x])continue;
            redfs(to,x,to);
        }
    }
    void buildtree(int rt,int l,int r)
    {
        tree[rt].maxv=tree[rt].lazy=-0x3f3f3f3f;
        if(l==r)
        {
            tree[rt].ori=dep[onum[l]]<<1;
            return;
        }
        int mid=(l+r)>>1;
        buildtree(rt1,l,mid),buildtree(rt2,mid+1,r);
        tree[rt].ori=max(tree[rt1].ori,tree[rt2].ori);
    }
    void pushdown(int rt)
    {
        tree[rt1].lazy=max(tree[rt1].lazy,tree[rt].lazy);
        tree[rt2].lazy=max(tree[rt2].lazy,tree[rt].lazy);
        tree[rt1].maxv=max(tree[rt1].maxv,tree[rt1].ori+tree[rt].lazy);
        tree[rt2].maxv=max(tree[rt2].maxv,tree[rt2].ori+tree[rt].lazy);
        tree[rt].lazy=-0x3f3f3f3f;
    }
    void update(int rt,int l,int r,int lq,int rq,int v)
    {
        if(l>=lq&&r<=rq)
        {
            tree[rt].lazy=max(tree[rt].lazy,v);
            tree[rt].maxv=max(tree[rt].maxv,tree[rt].ori+v);
            return;
        }
        if(tree[rt].lazy!=-0x3f3f3f3f)pushdown(rt);
        int mid=(l+r)>>1;
        if(lq<=mid)update(rt1,l,mid,lq,rq,v);
        if(rq>mid)update(rt2,mid+1,r,lq,rq,v);
        tree[rt].maxv=max(tree[rt1].maxv,tree[rt2].maxv);
    }
    int query(int rt,int l,int r,int lq,int rq)
    {
        if(l>=lq&&r<=rq)return tree[rt].maxv;
        if(tree[rt].lazy!=-0x3f3f3f3f)pushdown(rt);
        int mid=(l+r)>>1;
        int s=-0x3f3f3f3f;
        if(lq<=mid)s=max(s,query(rt1,l,mid,lq,rq));
        if(rq>mid)s=max(s,query(rt2,mid+1,r,lq,rq));
        return s;
    }
    int solve(int p,int tim)
    {
        int u=p;
        while(u)
        {
            int t=ttop[u];
            if(query(1,1,n,nnum[t],nnum[u])<=dep[p]+tim){u=f[ttop[u]];continue;}
            int l=nnum[t],r=nnum[u],ans=r;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(query(1,1,n,mid,r)>dep[p]+tim)ans=mid,l=mid+1;
                else r=mid-1;
            }
            u=onum[ans];break;
        }
        if(!u)u=1;
        int re=2*(dep[p]-dep[u])+tim;
        int tp=p;
        while(ttop[tp]!=ttop[u])update(1,1,n,nnum[ttop[tp]],nnum[tp],re-dep[p]),tp=f[ttop[tp]];
        update(1,1,n,nnum[u]+1,nnum[tp],re-dep[p]);
        return re;
    }
    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;
    }
    int main()
    {
        n=read()+1,m=read();
        for(int i=2;i<=n;i++)f[i]=read()+1,v[f[i]].push_back(i);
        dfs(1,0),redfs(1,0,1),buildtree(1,1,n);
        for(int i=1;i<=m;i++)q[i].p=read()+1,q[i].t=read(),q[i].num=i;
        sort(q+1,q+m+1);
        for(int i=1;i<=m;i++)ret[q[i].num]=solve(q[i].p,q[i].t);
        for(int i=1;i<=m;i++)printf("%d
    ",ret[i]);
        return 0;
    }
  • 相关阅读:
    php2
    11-14php
    三层嵌套
    常见的浏览器兼容
    css中的一些问题及解决方法
    css
    html
    测试题
    正则表达式
    Math对象
  • 原文地址:https://www.cnblogs.com/zhangleo/p/11112551.html
Copyright © 2011-2022 走看看