zoukankan      html  css  js  c++  java
  • [IOI 2018] Werewolf

    [题目链接]

             https://www.luogu.org/problemnew/show/P4899

    [算法] 

            建出原图的最小/最大生成树的kruskal重构树然后二维数点

            时间复杂度 : O((N+Q)logN)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    #define N 200010
    #define M 400010
    #define MAXLOG 20
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
    template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
    template <typename T> inline void read(T &x)
    {
       T f = 1; x = 0;
       char c = getchar();
       for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
       for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
       x *= f;
    }
    
    struct info
    {
        int x , y;
    } a[M];
    struct edge
    {
        int to , nxt;
    } ea[N << 2] , eb[N << 2];
    
    int n , m , q , tot , timera , timerb , cnta , cntb;
    int la[N << 1] , ra[N << 1] , fathera[N << 1][MAXLOG] , fatherb[N << 1][MAXLOG] , 
        deptha[N << 1] , depthb[N << 1] , rt[N << 1] , heada[N << 1] , headb[N << 1] ,
        lb[N << 1] , rb[N << 1] , fa[N << 1] , valuea[N << 1] , valueb[N << 1] , w[N << 1];
    
    struct Presitent_Segment_Tree 
    {
        int sz;
        Presitent_Segment_Tree()
        {
            sz = 0;
        }
        struct node
        {
            int lc , rc;    
            int cnt;
        } a[N * 60];
        inline void modify(int &now , int old , int l , int r , int x , int value)
        {
            now = ++sz;
            a[now].lc = a[old].lc , a[now].rc = a[old].rc;
            a[now].cnt = a[old].cnt + value;
            if (l == r) return;
            int mid = (l + r) >> 1;
            if (mid >= x) modify(a[now].lc , a[old].lc , l , mid , x , value);
            else modify(a[now].rc , a[old].rc , mid + 1 , r , x , value);
        }
        inline int query(int rt1 , int rt2 , int l , int r , int ql , int qr)
        {
            if (l == ql && r == qr)
                return a[rt1].cnt - a[rt2].cnt;
            int mid = (l + r) >> 1;
            if (mid >= qr) return query(a[rt1].lc , a[rt2].lc , l , mid , ql , qr);
            else if (mid + 1 <= ql) return query(a[rt1].rc , a[rt2].rc , mid + 1 , r , ql , qr);
            else return query(a[rt1].lc , a[rt2].lc , l , mid , ql , mid) + query(a[rt1].rc , a[rt2].rc , mid + 1 , r , mid + 1 , qr);
        }
    } PST;
    inline void addedgea(int u , int v)
    {
        ++tot;
        ea[tot] = (edge){v , heada[u]};
        heada[u] = tot;
    }
    inline void addedgeb(int u , int v)
    {
        ++tot;
        eb[tot] = (edge){v , headb[u]};
        headb[u] = tot;
    }
    inline void dfsa(int u , int par)
    {
        fathera[u][0] = par;
        deptha[u] = deptha[par] + 1;
        for (int i = 1; i < MAXLOG; i++)
            fathera[u][i] = fathera[fathera[u][i - 1]][i - 1];
        la[u] = ++timera;
        for (int i = heada[u]; i; i = ea[i].nxt)
        {
            int v = ea[i].to;
            if (v == par) continue;
            dfsa(v , u);
        }
        ra[u] = timera;
    }
    inline void dfsb(int u , int par)
    {
        fatherb[u][0] = par;
        depthb[u] = depthb[par] + 1;
        for (int i = 1; i < MAXLOG; i++)
            fatherb[u][i] = fatherb[fatherb[u][i - 1]][i - 1];
        lb[u] = ++timerb;
        for (int i = headb[u]; i; i = eb[i].nxt)
        {
            int v = eb[i].to;
            if (v == par) continue;
            dfsb(v , u);
        }
        rb[u] = timerb;
    }
    inline bool cmpa(info a , info b)
    {
        return min(a.x , a.y) > min(b.x , b.y);
    }
    inline bool cmpb(info a , info b)
    {
        return max(a.x , a.y) < max(b.x , b.y);
    }
    inline int getroot(int x)
    {
        if (fa[x] == x) return x;
        else return fa[x] = getroot(fa[x]);
    }
    inline void kruskalA()
    {
        int tot = 0;
        cnta = n;
        timera = 0;
        sort(a + 1 , a + m + 1 , cmpa);
        for (int i = 1; i <= 2 * n; i++) fa[i] = i;
        for (int i = 1; i <= m; i++)
        {
            int fu = getroot(a[i].x) , fv = getroot(a[i].y);
            if (fu != fv)
            {
                ++cnta;
                addedgea(cnta , fu);
                addedgea(cnta , fv);
                valuea[cnta] = min(a[i].x , a[i].y);
                fa[fu] = fa[fv] = fa[cnta] = cnta;
                ++tot;
            }
            if (tot == n - 1) break; 
        }    
        dfsa(cnta , 0);
    }
    inline void kruskalB()
    {
        int tot = 0;
        cntb = n;
        timerb = 0;
        sort(a + 1 , a + m + 1 , cmpb);
        for (int i = 1; i <= 2 * n; i++) fa[i] = i;
        for (int i = 1; i <= m; i++)
        {
            int fu = getroot(a[i].x) , fv = getroot(a[i].y);
            if (fu != fv)
            {
                ++cntb;
                addedgeb(cntb , fu);
                addedgeb(cntb , fv);
                valueb[cntb] = max(a[i].x , a[i].y);
                fa[fu] = fa[fv] = fa[cntb] = cntb;
                ++tot;
            }
            if (tot == n - 1) break;
        }
        dfsb(cntb , 0);
    }
    inline bool query(int l1 , int r1 , int l2 , int r2)
    {
        return PST.query(rt[r1] , rt[l1 - 1] , 1 , 2 * n , l2 , r2);
    }
    
    int main()
    {
        
        read(n); read(m); read(q);
        for (int i = 1; i <= m; i++)
        {
            read(a[i].x);
            read(a[i].y);
            ++a[i].x; ++a[i].y;
        }
        kruskalA();
        kruskalB();
        for (int i = 1; i <= n; i++) w[la[i]] = lb[i];
        for (int i = 1; i <= 2 * n; i++) PST.modify(rt[i] , rt[i - 1] , 1 , 2 * n , w[i] , 1);
        for (int i = 1; i <= q; i++)
        {
            int s , e , l , r;
            read(s); read(e); read(l); read(r);
            ++s; ++e; ++l; ++r;
            if (s < l || e > r) 
            {
                puts("0");
                continue;
            }
            for (int i = MAXLOG - 1; i >= 0; i--)
                if (fathera[s][i] && valuea[fathera[s][i]] >= l)
                    s = fathera[s][i];
            for (int i = MAXLOG - 1; i >= 0; i--)
                if (fatherb[e][i] && valueb[fatherb[e][i]] <= r)
                    e = fatherb[e][i];
            if (query(la[s] , ra[s] , lb[e] , rb[e])) puts("1");
            else puts("0");
        }
        
        return 0;
    }
  • 相关阅读:
    JSONArray数据转换成java List
    js格式化格林威治时间
    JS实现等比例缩放图片
    oracle显示一个月的所有天数
    Oracle行转列、列转行的Sql语句总结
    当echarts的legend字数过多的时候变成省略号
    oracle获取今年在内的前几年、后几年
    JAVA方法调用中的解析与分派
    static 和 final 关键字 对实例变量赋初始值的影响
    从虚拟机指令执行的角度分析JAVA中多态的实现原理
  • 原文地址:https://www.cnblogs.com/evenbao/p/10372309.html
Copyright © 2011-2022 走看看