zoukankan      html  css  js  c++  java
  • luogu P4899 [IOI2018] werewolf 狼火

    传送门

    首先很显然,从人形起点出发能到的点和狼形能到终点的点都是一个联通块,如果能从起点到终点则说明这两个联通块有交

    这个时候可以请出我们的克鲁斯卡尔重构树,即对原图分别建两棵重构树,一棵边权为两端点较小值,边权从大到小排序后构建,另一棵反过来,所以构完后第一棵重构树某个点权值要小于等于子树内的点,第二棵某点权值大于等于子树内点

    对于一个询问,起点在第一棵树向上倍增找深度最浅,权值(ge l)的祖先x,终点在第二棵树向上倍增找深度最浅,权值(le l)的祖先y,那么x和y就是上面说到的联通块.现在问题转化为子树判交,把询问离线,把y挂在x上,在第一棵树内从叶子开始向上做,做到某个点就x查询对应y子树对应的dfn区间在线段树上有没有x子树的叶子节点

    代码极丑qwq

    // luogu-judger-enable-o2
    #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;
    const db eps=1e-5;
    il LL rd()
    {
        LL 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 ed[N<<2];
    struct edge
    {
        int x,y,w;
    }ee[N<<1];
    int ff[N<<1];
    il int findf(int x){return ff[x]==x?x:ff[x]=findf(ff[x]);}
    struct trr
    {
        int a[N<<1],fa[N<<1][20],ch[N<<1][2],sz[N<<1],dfn[N<<1],tt,s[N<<1],tp;
        trr(){tp=0;}
        il void init(int n){tt=n;}
        il void ad(int x,int y,int w){a[++tt]=w,ff[x]=ff[y]=fa[x][0]=fa[y][0]=tt,ch[tt][0]=x,ch[tt][1]=y;}
        void pree(int x)
        {
            if(!x) return;
            s[++tp]=x,dfn[x]=tp,sz[x]=1;
            for(int j=1;j<20;++j)
            {
                fa[x][j]=fa[fa[x][j-1]][j-1];
                if(!fa[x][j]) break;
            }
            pree(ch[x][0]),pree(ch[x][1]);
            sz[x]+=sz[ch[x][0]]+sz[ch[x][1]];
        }
        il int findd(int x,int p,bool op)
        {
            if(op) {for(int j=19;~j;--j) if(a[fa[x][j]]>=p) x=fa[x][j];}
            else {for(int j=19;~j;--j) if(fa[x][j]&&a[fa[x][j]]<=p) x=fa[x][j];}
            return x;
        }
    }tr[2];
    il bool cmp1(edge a,edge b){return a.w>b.w;}
    il bool cmp2(edge a,edge b){return a.w<b.w;}
    int qto[N<<1],qnt[N<<1],qhd[N<<1],qt;
    il void qwq(int x,int y){++qt,qto[qt]=y,qnt[qt]=qhd[x],qhd[x]=qt;}
    int n,m,q;
    bool an[N];
    struct sgmt
    {
        bool s[(N<<1)*30];
        int ch[(N<<1)*30][2],rt[N<<1],tt;
        sgmt(){tt=0;}
        il void inst(int o,int x)
        {
            int l=1,r=n+n-1;
            s[o]=1;
            while(l<r)
            {
                int mid=(l+r)>>1;
                if(x<=mid) o=ch[o][0]=++tt,r=mid;
                else o=ch[o][1]=++tt,l=mid+1;
                s[o]=1;
            }
        }
        int merge(int o1,int o2)
        {
            if(!o1||!o2) return o1+o2;
            if(o1==o2) return o1;
            int o=++tt;
            s[o]=s[o1]|s[o2];
            ch[o][0]=merge(ch[o1][0],ch[o2][0]);
            ch[o][1]=merge(ch[o1][1],ch[o2][1]);
            return o;
        }
        bool quer(int o,int l,int r,int ll,int rr)
        {
            if(!o) return 0;
            if(ll<=l&&r<=rr) return s[o];
            bool an=0;
            int mid=(l+r)>>1;
            if(ll<=mid) an|=quer(ch[o][0],l,mid,ll,rr);
            if(rr>mid) an|=quer(ch[o][1],mid+1,r,ll,rr);
            return an;
        }
    }sht;
    
    int main()
    {
        n=rd(),m=rd(),q=rd();
        tr[0].init(n),tr[1].init(n);
        for(int i=1;i<=n;++i) tr[0].a[i]=tr[1].a[i]=i;
        for(int i=1;i<=m;++i) ed[i<<1]=rd()+1,ed[i<<1|1]=rd()+1;
        for(int i=1;i<=m;++i) ee[i]=(edge){ed[i<<1],ed[i<<1|1],min(ed[i<<1],ed[i<<1|1])};
        sort(ee+1,ee+m+1,cmp1);
        for(int i=1;i<n+n;++i) ff[i]=i;
        for(int i=1;i<=m;++i) if(findf(ee[i].x)^findf(ee[i].y)) tr[0].ad(ff[ee[i].x],ff[ee[i].y],ee[i].w);
        tr[0].pree(n+n-1);
        for(int i=1;i<=m;++i) ee[i]=(edge){ed[i<<1],ed[i<<1|1],max(ed[i<<1],ed[i<<1|1])};
        sort(ee+1,ee+m+1,cmp2);
        for(int i=1;i<n+n;++i) ff[i]=i;
        for(int i=1;i<=m;++i) if(findf(ee[i].x)^findf(ee[i].y)) tr[1].ad(ff[ee[i].x],ff[ee[i].y],ee[i].w);
        tr[1].pree(n+n-1);
        for(int i=1;i<=q;++i)
        {
            int x=rd()+1,y=rd()+1,l=rd()+1,r=rd()+1;
            x=tr[0].findd(x,l,1),y=tr[1].findd(y,r,0);
            qwq(x,y);
        }
        for(int i=n+n-1;i;--i)
        {
            int x=tr[0].s[i];
            if(x<=n) sht.inst(sht.rt[x]=++sht.tt,tr[1].dfn[x]);
            else sht.rt[x]=sht.merge(sht.rt[tr[0].ch[x][0]],sht.rt[tr[0].ch[x][1]]);
            for(int j=qhd[x];j;j=qnt[j])
            {
                int xx=qto[j];
                an[j]=sht.quer(sht.rt[x],1,n+n-1,tr[1].dfn[xx],tr[1].dfn[xx]+tr[1].sz[xx]-1);
            }
        }
        for(int i=1;i<=q;++i) printf("%d
    ",an[i]);
        return 0;
    }
    
  • 相关阅读:
    java解析xml的几种方式
    Android Studio 问题解决List
    Android 无线调试方法
    Android 单选/复选控件
    clr
    jquery.metadata.js使用分析
    更改新建Asp.net WebForm的模板 的方法
    获取定位数据
    简易水平仪实现
    简易指南针实现
  • 原文地址:https://www.cnblogs.com/smyjr/p/10186880.html
Copyright © 2011-2022 走看看