• luogu P3250 [HNOI2016]网络


    传送门

    考虑只有一个询问,怎么使用暴力枚举最快的得到答案.因为要求最大的,所以可以把链按权值从大往小排序,然后往后扫,找到一个没有交的就是答案,直接退出

    一堆询问,可以考虑整体二分,先二分一个值(mid),然后从前往后扫,如果是加入/删除操作,并且权值(> mid)就把这个操作贡献记上;如果是询问,然后如果经过这个点的链个数( e)当前存在的链个数,说明答案(>mid),否则(le mid)

    然后剩下的套一个整体二分板子就好了.答案的话如果取值范围的(l=r),就可以直接更新答案.然后就是怎么算经过某个点的链条数,显然可以使用洛谷树链剖分模板题的代码(别用无脑线段树,这里只要单点求值),或者考虑树上差分,每次询问子树内权值和就是那个链条数

    #include<bits/stdc++.h>
    #define LL long long
    #define db double
    #define il inline
    #define re register
    
    using namespace std;
    const int N=2e5+10;
    il int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int to[N],nt[N],hd[N],tot=1;
    il void add(int x,int y)
    {
        ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
        ++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
    }
    int fa[N],sz[N],de[N],hs[N],top[N],dfn[N],ti;
    void dfs1(int x)
    {
        sz[x]=1;
        for(int i=hd[x];i;i=nt[i])
        {
            int y=to[i];
            if(y==fa[x]) continue;
            fa[y]=x,de[y]=de[x]+1,dfs1(y),sz[x]+=sz[y];
            hs[x]=sz[hs[x]]>sz[y]?hs[x]:y;
        }
    }
    void dfs2(int x,int ntp)
    {
        dfn[x]=++ti,top[x]=ntp;
        if(hs[x]) dfs2(hs[x],ntp);
        for(int i=hd[x];i;i=nt[i])
        {
            int y=to[i];
            if(y==fa[x]||y==hs[x]) continue;
            dfs2(y,y);
        }
    }
    int n,q;
    int c[N];
    void ad(int x,int y){while(x<=n) c[x]+=y,x+=x&(-x);}
    int gsm(int x){int an=0;while(x) an+=c[x],x-=x&(-x);return an;}
    void add(int x,int y,int z)
    {
        while(top[x]!=top[y])
        {
            if(de[top[x]]<de[top[y]]) swap(x,y);
            ad(dfn[top[x]],z),ad(dfn[x]+1,-z);
            x=fa[top[x]];
        }
        if(de[x]>de[y]) swap(x,y);
        ad(dfn[x],z),ad(dfn[y]+1,-z);
    }
    struct node
    {
        int x,y,z,k;
    }p[N],lp[N],rp[N];
    int an[N],m;
    void dc(int l,int r,int lx,int rx)
    {
        if(l>r||lx>rx) return;
        int sd=0;
        if(lx==rx)
        {
            for(int i=l;i<=r;++i)
            {
                if(p[i].k) sd+=p[i].k,add(p[i].x,p[i].y,p[i].k);
                else if(gsm(dfn[p[i].x])!=sd) an[p[i].y]=lx;
            }
            for(int i=l;i<=r;++i)
                if(p[i].k) sd+=p[i].k,add(p[i].x,p[i].y,-p[i].k);
            return;
        }
        int mid=(lx+rx)>>1;
        int tl=0,tr=0;
        for(int i=l;i<=r;++i)
        {
            if(p[i].k)
            {
                if(p[i].z<=mid) lp[++tl]=p[i];
                else 
                {
                    sd+=p[i].k;
                    rp[++tr]=p[i],add(p[i].x,p[i].y,p[i].k);
                }
            }
            else 
            {
                if(gsm(dfn[p[i].x])==sd) lp[++tl]=p[i];
                else
                {
                    rp[++tr]=p[i];
                }
            }
        }
        for(int i=1;i<=tl;++i) p[l+i-1]=lp[i];
        for(int i=1;i<=tr;++i) p[l+tl+i-1]=rp[i];
        for(int i=1;i<=tr;++i)
            if(rp[i].k) add(rp[i].x,rp[i].y,-rp[i].k);
        dc(l,l+tl-1,lx,mid),dc(l+tl,r,mid+1,rx);
    }
    
    int main()
    {
        n=rd(),q=rd();
        for(int i=1;i<n;++i) add(rd(),rd());
        dfs1(1),dfs2(1,1);
        for(int i=1;i<=q;++i)
        {
            int op=rd();
            if(op==0) p[i].x=rd(),p[i].y=rd(),p[i].z=rd(),p[i].k=1;
            else if(op==1)
            {
                int x=rd();
                p[i]=p[x],p[i].k=-1;
            }
            else p[i].x=rd(),an[p[i].y=++m]=-1;
        }
        dc(1,q,0,1<<30);
        for(int i=1;i<=m;++i) printf("%d
    ",an[i]);
        return 0;
    }
    
  • 相关阅读:
    如何保证access_token长期有效
    微信自定义菜单的创建
    是否同一棵二叉搜索树
    Tree Traversals Again(根据前序,中序,确定后序顺序)
    List Leaves 树的层序遍历
    leetcode-优美的排列
    leetcode-下一个排列
    leetcode-二进制手表
    leetcode-组合总数III(回溯)
    leetcode-累加数(C++)
  • 原文地址:https://www.cnblogs.com/smyjr/p/10410387.html
Copyright © 2020-2023  润新知