zoukankan      html  css  js  c++  java
  • [IOI2018] werewolf 狼人

    [IOI2018] werewolf 狼人

    IOI2018题解

    (其实原题强制在线,要用主席树)

    代码:

    注意:

    1.下标从0~n-1

    2.kruskal重构树开始有n个节点,tot从n开始,++tot

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int M=400000+5;
    const int N=400000+5;
    const int inf=0x3f3f3f3f;
    int n,m,Q;
    struct edge{
        int x,y;
        int val;
    }b[M];
    bool cmp0(edge a,edge b){
        return a.val<b.val;
    }
    bool cmp1(edge a,edge b){
        return a.val>b.val;
    }
    int fafa[2*N];
    
    struct kruskal{
        struct node{
            int nxt,to;
        }e[2*N];
        int hd[2*N],cnt;
        int fin(int x){
            return fafa[x]==x?x:fafa[x]=fin(fafa[x]);
        }
        void add(int x,int y){
            e[++cnt].nxt=hd[x];
            e[cnt].to=y;
            hd[x]=cnt;
        }
        int tot;
        void build(int typ){
            for(reg i=1;i<=n;++i){
                if(typ) val[i]=inf;
                else val[i]=-inf;
            }
            tot=n;
            for(reg i=1;i<=m;++i){
                int k1=fin(b[i].x),k2=fin(b[i].y);
        //        cout<<" edge "<<b[i].x<<" "<<b[i].y<<" :: "<<k1<<" "<<k2<<endl;
                if(k1!=k2){
                    ++tot;
                    fafa[tot]=tot;
                    fafa[k1]=tot;
                    fafa[k2]=tot;
                    val[tot]=b[i].val;
                    add(tot,k1);
                    add(tot,k2);
                }
            }
        }
        int l[N],r[N];
        int val[N];
        int fa[N][20];
        int df;
        void dfs(int x){
        //    cout<<" xx "<<x<<endl;
            int son=0;
            r[x]=-inf;l[x]=inf;
            for(reg i=hd[x];i;i=e[i].nxt){
                int y=e[i].to;
                ++son;
                dfs(y);
                fa[y][0]=x;
                r[x]=max(r[x],r[y]);
                l[x]=min(l[x],l[y]);
            }
            if(!son){
                l[x]=r[x]=++df;
            }
        }
        void pre(){
            dfs(tot);
            for(reg j=1;j<=19;++j){
                for(reg i=1;i<=tot;++i){
                    fa[i][j]=fa[fa[i][j-1]][j-1];
                }
            }
        }
        int fin(int x,int lim,int typ){//beizeng go val
            int p=x;
            if(!typ){//go <=lim
                for(reg j=19;j>=0;--j){
                    if(fa[p][j]){
                        if(val[fa[p][j]]<=lim) p=fa[p][j];
                    }
                }
                return p;
            }else{//go >=lim
                for(reg j=19;j>=0;--j){
                    if(fa[p][j]){
                        if(val[fa[p][j]]>=lim) p=fa[p][j];
                    }
                }
                return p;
            }
        }
    }kt[2];//0:min tree;1:max tree;
    
    int num;
    struct po{
        int x,y;
        bool friend operator <(po a,po b){
            return a.x<b.x;
        }
    }p[N];
    int ans[N];
    
    int tot;
    struct que{
        int id,x,typ,y1,y2;
        bool friend operator <(que a,que b){
            return a.x<b.x;
        }
    }q[N*2];
    
    
    struct binarytree{
        int f[N];
        void upda(int x){
            for(;x<=n;x+=x&(-x)) f[x]++;
        }
        int query(int x){
            int ret=0;
            for(;x;x-=x&(-x)) ret+=f[x];
            return ret;
        }
    }t;
    int main(){
        rd(n);rd(m);rd(Q);
        for(reg i=1;i<=m;++i){
            rd(b[i].x);rd(b[i].y);
            
            ++b[i].x;++b[i].y;//warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            
            b[i].val=max(b[i].x,b[i].y);
        }
        sort(b+1,b+m+1,cmp0);
        for(reg i=1;i<=2*n;++i){
            fafa[i]=i;
        }
        kt[0].build(0);
        
        kt[0].pre();
    //    cout<<" after build small "<<endl;
        for(reg i=1;i<=m;++i){
            b[i].val=min(b[i].x,b[i].y);
        }
        sort(b+1,b+m+1,cmp1);
        for(reg i=1;i<=2*n;++i){
            fafa[i]=i;
        }
        kt[1].build(1);
        kt[1].pre();
        
        int st,nd,L,R;
        for(reg i=1;i<=Q;++i){
            rd(st);rd(nd);rd(L);rd(R);
            ++L;++R;
            ++st;++nd;//warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            
            int ptr=kt[1].fin(st,L,1);
            q[++tot].id=i;
            q[tot].y1=kt[1].l[ptr];
            q[tot].y2=kt[1].r[ptr];
            
            q[++tot].id=i;
            q[tot].y1=kt[1].l[ptr];
            q[tot].y2=kt[1].r[ptr];
            
            ptr=kt[0].fin(nd,R,0);
            q[tot-1].x=kt[0].l[ptr]-1;
            q[tot].x=kt[0].r[ptr];
            
            q[tot-1].typ=-1;
            q[tot].typ=1;
        }
        sort(q+1,q+tot+1);
        
        for(reg i=1;i<=n;++i){
            p[i].x=kt[0].l[i];
            p[i].y=kt[1].l[i];
        }
        sort(p+1,p+n+1);
        
        int ptp=1,ptq=1;
        for(reg i=1;i<=n;++i){
            while(ptp<=n&&p[ptp].x<i) ++ptp;
            if(p[ptp].x==i){
                while(ptp<=n&&p[ptp].x==i){
                    t.upda(p[ptp].y);
                    ++ptp;
                }
            }
            
            while(ptq<=tot&&q[ptq].x<i) ++ptq;
            if(q[ptq].x==i){
                while(ptq<=tot&&q[ptq].x==i){
                    ans[q[ptq].id]+=q[ptq].typ*(t.query(q[ptq].y2)-t.query(q[ptq].y1-1));
                    ++ptq;
                }
            }
        }
        
        for(reg i=1;i<=Q;++i){
            puts(ans[i]?"1":"0");
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/2/10 15:50:00
    */

     总结:
    kruskal重构树,就是考虑在经过边权在一定范围内到达的区域的点的情况

    这里就是简单查询连通性

    两个重构树判交的“二维数点”问题的转化很巧妙!

  • 相关阅读:
    相关术语随笔
    JDK简介和mac下安装和查看版本命令
    英语
    英语学习2
    英语学习-19.1
    为什么java是只有值传递而没有引用传递
    线程
    关于同步异步

    jdk动态代理实现原理总结
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10359586.html
Copyright © 2011-2022 走看看