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

    UOJ 407

    kruskal重构树

    所有边的边权记为两个点的$max$建立一棵重构树,这样子可以做出一个点走不超过$R$能到达的点的集合,再把所有边的边权记为两个点的$min$建立重构树,这样子可以做出一个点走不少于$L$所能到达的点的集合

    注意到这两个集合其实是重构树叶子的一段区间,问题有解等价于区间有交,这样子就变成了一个二维数点问题

    暴力线段树合并过不去,别问我是怎么知道的

    一开始交的时候边数开错了

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include "werewolf.h"
    using namespace std;
    
    const int N = 8e5 + 5;
    const int M = 2e5 + 5;
    const int Lg = 22;
    const int inf = 1 << 30;
    
    int n, m, qn, tot = 0, head[N], ufs[N];
    int rt1, rt2, ncnt, w[N], fa[N][Lg];
    int ln[N], rn[N], dfsc = 0, id1[M], id2[M], px1[M], px2[M], ans[M];
    
    struct Edge {
        int to, nxt;
    } e[N];
    
    inline void add(int from, int to) {
        e[++tot].to = to;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    struct Path {
        int u, v, val;
    
        friend bool operator < (const Path x, const Path y) {
            return x.val < y.val;
        }
    
    } pat[M << 1];
    
    struct Query {
        int s, t, lv, rv;
    } q[M];
    
    struct Seg {
        int l, r, id, type;
    };
    vector <Seg> vec[M];
    
    namespace Fread {
        const int L = 1 << 15;
        
        char buffer[L], *S, *T;
        
        inline char Getchar() {
            if(S == T) {
                T = (S = buffer) + fread(buffer, 1, L, stdin);
                if(S == T) return EOF;
            }
            return *S++;
        }
        
        template <class T> 
        inline void read(T &X) {
            char ch; T op = 1;
            for(ch = Getchar(); ch > '9' || ch < '0'; ch = Getchar())
                if(ch == '-') op = -1;
            for(X = 0; ch >= '0' && ch <= '9'; ch = Getchar()) 
                X = (X << 1) + (X << 3) + ch - '0'; 
            X *= op;
        }
        
    } using Fread :: read;   
    
    namespace Fwrite {
        const int L = 1 << 15;
        
        char buf[L], *pp = buf;
        
        void Putchar(const char c) {
            if(pp - buf == L) fwrite(buf, 1, L, stdout), pp = buf;
            *pp++ = c;
        }
        
        template<typename T>
        void print(T x) {
            if(x < 0) {
                Putchar('-');
                x = -x;
            }
            if(x > 9) print(x / 10);
            Putchar(x % 10 + '0');
        }
        
        void fsh() {
            fwrite(buf, 1, pp - buf, stdout);
            pp = buf;
        }
        
        template <typename T>
        inline void write(T x, char ch = 0) {
            print(x);
            if (ch != 0) Putchar(ch);
        }
    
    } using Fwrite :: write;
    
    /*
    namespace SegT {
        struct Node {
            int lc, rc, sum;
        } s[N * 20];
        
        int root[N], pcnt = 0, top = 0, pool[N * 20];
    
        #define lc(p) s[p].lc
        #define rc(p) s[p].rc
        #define sum(p) s[p].sum
        #define mid ((l + r) >> 1)
    
        inline void up(int p) {
            if (!p) return;
            sum(p) = sum(lc(p)) + sum(rc(p));
        }
    
        inline int newNode() {
            if (top) return pool[top--];
            else return ++pcnt;
        }
    
        inline void del(int p) {
            pool[++top] = p;
        }
    
        int merge(int u, int v, int l, int r) {
            if (!u || !v) return u + v;
            int p = newNode();
            if (l == r) {
                sum(p) = sum(u) + sum(v);
            } else {
                lc(p) = merge(lc(u), lc(v), l, mid);
                rc(p) = merge(rc(u), rc(v), mid + 1, r);
                up(p);    
            }
            del(u), del(v);
            return p;
        }
    
        void build(int &p, int l, int r, int x) {
            if (!p) p = newNode();
            if (l == r) {
                ++sum(p);
                return;
            }
            if (x <= mid) build(lc(p), l, mid, x);
            else build(rc(p), mid + 1, r, x);
            up(p);
        }
    
        int query(int p, int l, int r, int x, int y) {
            if (!p) return 0;
            if (x <= l && y >= r) return sum(p);
            int res = 0;
            if (x <= mid) res += query(lc(p), l, mid, x, y);
            if (y > mid) res += query(rc(p), mid + 1, r, x, y);
            up(p);
            return res;
        }
    
        void print(int k) {
            printf("%d : ", k);
            for (int i = 1; i <= n; i++)
                printf("%d ", query(root[k], 1, n, i, i));
            puts("");
        }
    
        #undef mid
    
    } using namespace SegT;    */
    
    int find(int x) {
        return ufs[x] == x ? x : ufs[x] = find(ufs[x]);
    }
    
    void dfs1(int x, int fat) {
        bool isLeaf = 1; 
        ln[x] = inf, rn[x] = -inf;
        fa[x][0] = fat;
        for (int i = 1; i <= 20; i++) fa[x][i] = fa[fa[x][i - 1]][i - 1];
        for (int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            isLeaf = 0;
            dfs1(y, x);
            ln[x] = min(ln[x], ln[y]);
            rn[x] = max(rn[x], rn[y]);
        }
        if (isLeaf) {
            id1[++dfsc] = x; 
            px1[x] = dfsc;
            ln[x] = rn[x] = dfsc;
        }
    }
    
    void dfs2(int x, int fat) {
        bool isLeaf = 1; 
        ln[x] = inf, rn[x] = -inf;
        fa[x][0] = fat;
        for (int i = 1; i <= 20; i++) fa[x][i] = fa[fa[x][i - 1]][i - 1];
        for (int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            isLeaf = 0;
            dfs2(y, x);
            ln[x] = min(ln[x], ln[y]);
            rn[x] = max(rn[x], rn[y]);
        }
        if (isLeaf) {
            id2[++dfsc] = x - 2 * n;
            px2[x - 2 * n] = dfsc;
            ln[x] = rn[x] = dfsc;
        }
    }
    
    inline int getPos1(int x, int val) {
        w[0] = inf;
        for (int i = 20; i >= 0; i--)
            if (w[fa[x][i]] <= val) x = fa[x][i];
        return x;
    }
    
    inline int getPos2(int x, int val) {
        w[0] = 0;
        for (int i = 20; i >= 0; i--)
            if (w[fa[x][i]] >= val) x = fa[x][i];
        return x;
    }   
    
    /* void solve(int x, int fat) {
        stk[++tp] = x;
        for (int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            solve(y, x);
            root[x] = merge(root[x], root[y], 1, n);
        }
    
        int siz = vec[x].size();
        for (int i = 0; i < siz; i++) {
            int qid = vec[x][i];
            int pos = getPos2(q[qid].s + 2 * n, q[qid].lv);
    //        printf("%d %d
    ", qid, pos);
            ans[qid] = query(root[x], 1, n, ln[pos - 2 * n], rn[pos - 2 * n]);
        }
    
    //    print(x);
        --tp;
    }    */
    
    void debug(int x, int fat, bool is2 = 0) {
        printf("%d:%d
    ", x, w[x]);
        if (is2) printf("%d::%d %d
    ", x, ln[x - 2 * n], rn[x - 2 * n]);
        for (int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            printf("%d %d
    ", x, y);
            debug(y, x);
        }
    }
    
    namespace Bit {
        int s[M];
    
        #define lowbit(p) (p & (-p))
    
        inline void modify(int p) {
            for (; p <= n; p += lowbit(p)) ++s[p];
        }
    
        inline int query(int p) {
            int res = 0;
            for (; p > 0; p -= lowbit(p)) res += s[p];
            return res;
        }
    
    } using namespace Bit;
    
    /*int main() {
        #ifndef ONLINE_JUDGE
            freopen("sample.in", "r", stdin);
            freopen("my.out", "w", stdout);
        #endif
    
        read(n), read(m), read(qn);
        for (int i = 1; i <= m; i++) {
            read(pat[i].u), read(pat[i].v);
            ++pat[i].u, ++pat[i].v;
            pat[i].val = max(pat[i].u, pat[i].v);
        }
    
        for (int i = 1; i <= 4 * n; i++) ufs[i] = i;
        ncnt = n;
        sort(pat + 1, pat + 1 + m);
        for (int cnt = 0, i = 1; i <= m; i++) {
            int u = pat[i].u, v = pat[i].v;
            int fu = find(u), fv = find(v);
            if (fu == fv) continue;
            ++cnt, ++ncnt;
            w[ncnt] = pat[i].val;
            ufs[fu] = ufs[fv] = ncnt;
            add(ncnt, fu), add(ncnt, fv);
            if (cnt == n - 1) break;
        }
        rt1 = find(1), dfsc = 0;
        dfs1(rt1, 0);
    
        // debug(rt1, 0);
    
        for (int i = 1; i <= m; i++) pat[i].val = min(pat[i].u, pat[i].v);
        ncnt = 3 * n;
        sort(pat + 1, pat + 1 + m); 
        for (int cnt = 0, i = m; i >= 1; i--) {
            int u = pat[i].u + 2 * n, v = pat[i].v + 2 * n;
            int fu = find(u), fv = find(v);
            if (fu == fv) continue;
            ++cnt, ++ncnt;
            w[ncnt] = pat[i].val;
            ufs[fu] = ufs[fv] = ncnt;
            add(ncnt, fu), add(ncnt, fv);
            if (cnt == n - 1) break;
        }
        rt2 = find(2 * n + 1), dfsc = 0;
        dfs2(rt2, 0);
        
        // puts("");
        // debug(rt2, 0, 1);
        // for (int i = 1; i <= n; i++)
        //     printf("%d%c", id[i], " 
    "[i == n]);   
    
        // for (int i = 1; i <= n; i++)
        //     printf("%d ", id1[i]);
        // printf("
    ");
        // for (int i = 1; i <= n; i++)
        //     printf("%d ", id2[i]);
        // printf("
    ");
        // for (int i = 1; i <= n; i++)
        //     printf("%d ", px2[id1[i]]);
        // printf("
    ");
    
        for (int i = 1; i <= qn; i++) {
            read(q[i].s), read(q[i].t), read(q[i].lv), read(q[i].rv);
            ++q[i].s, ++q[i].t, ++q[i].lv, ++q[i].rv;
            int pos1 = getPos1(q[i].t, q[i].rv), pos2 = getPos2(q[i].s + 2 * n, q[i].lv);
    //        printf("%d %d %d %d
    ", ln[pos1], rn[pos1], ln[pos2], rn[pos2]);
            vec[ln[pos1] - 1].push_back((Seg) {ln[pos2], rn[pos2], i, -1});
            vec[rn[pos1]].push_back((Seg) {ln[pos2], rn[pos2], i, 1});
        }
        for (int i = 1; i <= n; i++) {
            int siz = vec[i].size();
            modify(px2[id1[i]]);
            for (int j = 0; j < siz; j++) {
                int l = vec[i][j].l, r = vec[i][j].r, t = vec[i][j].type, qid = vec[i][j].id;
                ans[qid] += t * (query(r) - query(l - 1));
            }
        }
    
        // for (int i = 1; i <= qn; i++)
        //     write(ans[i] > 0 ? 1 : 0, '
    ');
    
        for (int i = 1; i <= qn; i++)
            write(ans[i] > 0 ? 1 : 0, '
    ');
        Fwrite :: fsh();
        return 0;
    }   */
    
    vector<int> check_validity(int N, vector<int> X, vector<int> Y, vector<int> S, vector<int> E, vector<int> L, vector<int> R) {
        // read(n), read(m), read(qn);
        n = N, m = X.size(), qn = S.size();
        for (int i = 1; i <= m; i++) {
            // read(pat[i].u), read(pat[i].v);
            pat[i].u = X[i - 1], pat[i].v = Y[i - 1];
            ++pat[i].u, ++pat[i].v;
            pat[i].val = max(pat[i].u, pat[i].v);
        }
    
        for (int i = 1; i <= 4 * n; i++) ufs[i] = i;
        ncnt = n;
        sort(pat + 1, pat + 1 + m);
        for (int cnt = 0, i = 1; i <= m; i++) {
            int u = pat[i].u, v = pat[i].v;
            int fu = find(u), fv = find(v);
            if (fu == fv) continue;
            ++cnt, ++ncnt;
            w[ncnt] = pat[i].val;
            ufs[fu] = ufs[fv] = ncnt;
            add(ncnt, fu), add(ncnt, fv);
            if (cnt == n - 1) break;
        }
        rt1 = find(1), dfsc = 0;
        dfs1(rt1, 0);
    
        // debug(rt1, 0);
    
        for (int i = 1; i <= m; i++) pat[i].val = min(pat[i].u, pat[i].v);
        ncnt = 3 * n;
        sort(pat + 1, pat + 1 + m); 
        for (int cnt = 0, i = m; i >= 1; i--) {
            int u = pat[i].u + 2 * n, v = pat[i].v + 2 * n;
            int fu = find(u), fv = find(v);
            if (fu == fv) continue;
            ++cnt, ++ncnt;
            w[ncnt] = pat[i].val;
            ufs[fu] = ufs[fv] = ncnt;
            add(ncnt, fu), add(ncnt, fv);
            if (cnt == n - 1) break;
        }
        rt2 = find(2 * n + 1), dfsc = 0;
        dfs2(rt2, 0);
        
        // puts("");
        // debug(rt2, 0, 1);
        // for (int i = 1; i <= n; i++)
        //     printf("%d%c", id[i], " 
    "[i == n]);   
    
        // for (int i = 1; i <= n; i++)
        //     printf("%d ", id1[i]);
        // printf("
    ");
        // for (int i = 1; i <= n; i++)
        //     printf("%d ", id2[i]);
        // printf("
    ");
        // for (int i = 1; i <= n; i++)
        //     printf("%d ", px2[id1[i]]);
        // printf("
    ");
    
        for (int i = 1; i <= qn; i++) {
            // read(q[i].s), read(q[i].t), read(q[i].lv), read(q[i].rv);
            q[i].s = S[i - 1], q[i].t = E[i - 1], q[i].lv = L[i - 1], q[i].rv = R[i - 1];
            ++q[i].s, ++q[i].t, ++q[i].lv, ++q[i].rv;
            int pos1 = getPos1(q[i].t, q[i].rv), pos2 = getPos2(q[i].s + 2 * n, q[i].lv);
    //        printf("%d %d %d %d
    ", ln[pos1], rn[pos1], ln[pos2], rn[pos2]);
            vec[ln[pos1] - 1].push_back((Seg) {ln[pos2], rn[pos2], i, -1});
            vec[rn[pos1]].push_back((Seg) {ln[pos2], rn[pos2], i, 1});
        }
        for (int i = 1; i <= n; i++) {
            int siz = vec[i].size();
            modify(px2[id1[i]]);
            for (int j = 0; j < siz; j++) {
                int l = vec[i][j].l, r = vec[i][j].r, t = vec[i][j].type, qid = vec[i][j].id;
                ans[qid] += t * (query(r) - query(l - 1));
            }
        }
    
        // for (int i = 1; i <= qn; i++)
        //     write(ans[i] > 0 ? 1 : 0, '
    ');
    
        // for (int i = 1; i <= qn; i++)
        //     write(ans[i] > 0 ? 1 : 0, '
    ');
        // Fwrite :: fsh();
        vector <int>  retAns;
        for (int i = 1; i <= qn; i++) retAns.push_back(ans[i] > 0 ? 1 : 0);
        return retAns;
    }
    View Code
  • 相关阅读:
    可自主二次开发的微信云控客服crm系统软件(带源码)
    个人微信号二次开发sdk协议,微信个人号开发API接口
    最新的微信SCRM客服系统
    微信个人号客服系统淘宝客发单机器人sdk服务端接口列表
    sdk定制开发微信群控云控客服系统教程
    web版微信自动发消息(实现微信个人号机器人)
    Adobe Audition 基本使用
    MPEG-7 视觉描述符
    图像检索:几种基于纹理特征的图像检索算法
    div+css基础教程
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/13852597.html
Copyright © 2011-2022 走看看