zoukankan      html  css  js  c++  java
  • CF226E Noble Knight's Path/bzoj4704 旅行

    题目描述:

    bz

    luogu

    题解:

    主席树维护大力树剖。

    一条路径上不允许过的点的个数是当前袭击数-$y$时袭击数,

    所以允许经过的点的个数是总数-当前袭击数+$y$时袭击数。

    用主席树去维护每个时刻树链袭击数。

    这样的话修改的时间复杂度是$O(nlogn)$的。

    现在的问题是查询。

    注意端点不算路径上的点,那么我们可以让起点和终点距离近一点。

    然后有两种情况,起点先向上走/先向下走。

    这两个都能用同样的暴跳二分解决。

    上代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 100050;
    const int M = 80*N;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    int n,m,hed[N],cnt,rot;
    struct EG{int to,nxt;}e[N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    int dep[N],siz[N],top[N],fa[N],son[N],tin[N],tim,pla[N];
    void dfs0(int u,int f)
    {
        fa[u] = f,siz[u] = 1,dep[u] = dep[f]+1;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            dfs0(to,u);siz[u]+=siz[to];
            if(siz[to]>siz[son[u]])son[u]=to;
        }
    }
    void dfs1(int u,int Top)
    {
        top[u] = Top,tin[u] = ++tim,pla[tim] = u;
        if(son[u])dfs1(son[u],Top);
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to!=son[u])dfs1(to,to);
        }
    }
    int get_lca(int x,int y)
    {
        while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);x=fa[top[x]];}
        return dep[x]<dep[y]?x:y;
    }
    int get_son(int x,int y)
    {
        while(top[x]!=top[y]){if(fa[top[x]]==y)return top[x];x=fa[top[x]];}
        return pla[tin[y]+1];
    }
    int rt[N];
    struct pertree
    {
        int tot,ls[M],rs[M],siz[M];
        void insert(int l,int r,int&u,int las,int qx)
        {
            u = ++tot;
            ls[u] = ls[las],rs[u] = rs[las],siz[u] = siz[las]+1;
            if(l==r)return ;
            int mid = (l+r)>>1;
            if(qx<=mid)insert(l,mid,ls[u],ls[las],qx);
            else insert(mid+1,r,rs[u],rs[las],qx);
        }
        int query(int l,int r,int L,int R,int ql,int qr)
        {
            if(!L&&!R)return 0;
            if(l==ql&&r==qr)return siz[R]-siz[L];
            int mid = (l+r)>>1;
            if(qr<=mid)return query(l,mid,ls[L],ls[R],ql,qr);
            else if(ql>mid)return query(mid+1,r,rs[L],rs[R],ql,qr);
            else return query(l,mid,ls[L],ls[R],ql,mid)+query(mid+1,r,rs[L],rs[R],mid+1,qr);
        }
    }tr;
    int query(int x,int y,int las,int now)
    {
        int ret = 0;
        while(top[x]!=top[y])
        {
            ret+=dep[x]-dep[top[x]]+1-tr.query(1,n,rt[las],rt[now],tin[top[x]],tin[x]);
            x = fa[top[x]];
        }
        return ret+dep[x]-dep[y]+1-tr.query(1,n,rt[las],rt[now],tin[y],tin[x]);
    }
    int dv(int l,int r,int las,int now,int k)
    {
        int ret = l-1;int tmp = r;
        while(l<=r)
        {
            int mid = (l+r)>>1;
            if(tmp-mid+1-tr.query(1,n,rt[las],rt[now],mid,tmp)>=k)ret=mid,l=mid+1;
            else r=mid-1;
        }
        return pla[ret];
    }
    int jmp(int x,int y,int las,int now,int k)
    {
        while(top[x]!=top[y])
        {
            int tmp = dep[x]-dep[top[x]]+1-tr.query(1,n,rt[las],rt[now],tin[top[x]],tin[x]);
            if(k>tmp)k-=tmp,x=fa[top[x]];
            else return dv(tin[top[x]],tin[x],las,now,k);
        }
        return dv(tin[y],tin[x],las,now,k);
    }
    int main()
    {
    //    freopen("tt.in","r",stdin);
        read(n);
        for(int f,i=1;i<=n;i++)
        {
            read(f);
            if(!f)rot=i;
            else ae(f,i);
        }
        dfs0(rot,0),dfs1(rot,rot);
        read(m);
        for(int op,a,b,c,k,y,i=1;i<=m;i++)
        {
            read(op);
            if(op==1)
            {
                read(c);
                tr.insert(1,n,rt[i],rt[i-1],tin[c]);
            }else
            {
                rt[i]=rt[i-1];
                read(a),read(b),read(k),read(y);
                if(fa[a]==b||fa[b]==a){puts("-1");continue;}
                int Lca = get_lca(a,b);
                if(a!=Lca&&b!=Lca)a=fa[a],b=fa[b];
                else if(a==Lca)b=fa[b],a=get_son(b,a);
                else a=fa[a],b=get_son(a,b);
                Lca = get_lca(a,b);
                if(a==Lca)
                {
                    int sum = query(b,a,y,i);
                    if(sum<k){puts("-1");continue;}
                    printf("%d
    ",jmp(b,a,y,i,sum-k+1));
                }else
                {
                    int alc = get_son(a,Lca);
                    int sum = query(a,alc,y,i);
                    if(sum>=k){printf("%d
    ",jmp(a,alc,y,i,k));continue;}
                    k-=sum;
                    sum = query(b,Lca,y,i);
                    if(sum<k){puts("-1");continue;}
                    printf("%d
    ",jmp(b,Lca,y,i,sum-k+1));
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    checkbox 实现单选效果(html)
    HDU-6850 Game
    牛客练习赛29----F 算式子
    牛客多校第二场 B Boundary
    D. Omkar and Circle
    【洛谷】P3306 [SDOI2013]---- 随机数生成器
    二次剩余
    【洛谷】--P2704 [NOI2001]炮兵阵地
    【洛谷】4310 绝世好题
    快速排序
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/11100901.html
Copyright © 2011-2022 走看看