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

    好像很久没更博客了呢~

    [IOI2018]werewolf狼人

    题目链接

    洛谷

    题解

    可以将题意转化为
    求从(S)出发只经过大于(L)的点构成的集合(∩)(E)只经过小于(R)的点是否为空。
    我们建(2)(kruskal)重构树(A,B)
    (A)为每条边的两个点中取较小的点为权值所构成的最大生成树对应的重构树。
    (B)为每条边的两个点中取较大的点为权值所构成的最小生成树对应的重构树。
    接着这(2)个集合直接在(A,B)上倍增找一下就好了。
    同时我们把每个点的开始(dfs)序和结束(dfs)序求出来。
    这就变成了一个序列问题。
    直接找个数据结构维护一下就好了。

    代码

    #include <bits/stdc++.h>
    
    namespace con_fast_io {
    char buf[1 << 12], *p1 = buf, *p2 = buf, SR[1 << 23], z[23]; int Z = 0, C = -1;
    inline void Ot() { fwrite(SR, 1, C + 1, stdout); C = -1; }
    inline void flush() { if (C > 1 << 22) Ot(); }
    inline char getc() {
      return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 12, stdin), p1 == p2) ? EOF : *p1++;
    }
    template<class t> inline void read(t& x) {
      x = 0; int fl = 1; char nc;
      while (nc = getc(), (nc < 48 || nc > 57) && (~nc)) if (nc == 45) fl = -1;
      x = nc - 48; while (nc = getc(), 47 < nc && nc < 58) x = (x << 1) + (x << 3) + (nc ^ 48);
      x *= fl;
    };
    template<class t> inline void write(t x, char c) {
      int y = 0; if (x < 0) y = 1, x = -x; while (z[++Z] = x % 10 + 48, x /= 10);
      if (y) z[++Z] = '-'; while(SR[++C] = z[Z], Z--); SR[++C] = c; flush();
    }
    inline void write(char* s) {
      int le = strlen(s);
      for (int i = 0; i < le; i++) SR[++C] = *s++;
      flush();
    }
    /*char z[23]; int Z = 0;
    inline void Ot() {}
    template<class t> inline void read(t& x) {
      x = 0; int fl = 1; char nc;
      while (nc = getchar(), (nc < 48 || nc > 57) && (~nc)) if (nc == 45) fl = -1;
      x = nc - 48; while (nc = getchar(), 47 < nc && nc < 58) x = (x << 1) + (x << 3) + (nc ^ 48);
      x *= fl;
    }
    template<class t> inline void write(t x, char c) {
      Z = 0; int y = 0; if (x < 0) y = 1, x = -x; z[++Z] = c;
      while (z[++Z] = x % 10 + 48, x /= 10);
      if (y) z[++Z] = '-'; while (Z) putchar(z[Z--]);
    }
    inline void write(char* s) { printf("%s
    ", s); }*/
    }
    using namespace con_fast_io;
    const int maxn = 2e5 + 600;
    const int maxm = 4e5 + 1500;
    const int inf = 0x3f3f3f3f;
    
    int n, m, i, j, k, q, cnto, val[maxn];
    struct edge {
      int u, v; edge() { u = v = 0; } edge(int _u, int _v) { u = _u, v = _v; }
    } e[maxm];
    inline bool cmp1(edge a, edge b) { return std::min(a.u, a.v) > std::min(b.u, b.v); }
    inline bool cmp2(edge a, edge b) { return std::max(a.u, a.v) < std::max(b.u, b.v); }
    struct ufs_t {
      int fa[maxm];
      inline void init(int j) { for (int i = 1; i <= j; i++) fa[i] = i; }
      int find(int u) { return u == fa[u] ? u : fa[u] = find(fa[u]); }
    } ufs;
    struct kruskal_rebuild_tree_t {
      int cnte, tim, hd[maxm], ver[maxm], nxt[maxm], fa[maxm][25], st[maxm], ed[maxm];
      int val[maxm], dfn[maxm];
      inline void adde(int u, int v) {
        ver[++cnte] = v, nxt[cnte] = hd[u], hd[u] = cnte;
      }
      void dfs(int u) {
        if (u <= n) dfn[++tim] = u, val[u] = u, st[u] = tim; else st[u] = tim + 1;
        for (int i = 1; i <= 20; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
        for (int i = hd[u], v; i; i = nxt[i]) {
          v = ver[i];
          fa[v][0] = u;
          dfs(v);
        }
        ed[u] = tim;
      }
      inline void work(int type) {
        ufs.init(n << 1);
        if (!type) std::sort(e + 1, e + m + 1, cmp1);
        else std::sort(e + 1, e + m + 1, cmp2);
        int tot = n;
        for (int i = 1; i <= m; i++) {
          int u = e[i].u, v = e[i].v, w = type ? std::max(u, v) : std::min(u, v);
          int ru = ufs.find(u), rv = ufs.find(v);
          if (ru == rv) continue;
          ufs.fa[ru] = ufs.fa[rv] = ++tot;
          val[tot] = w, adde(tot, ru), adde(tot, rv);
        }
       // exit(0);
        dfs(tot);
      }
      inline int getL(int u, int l) {
        for (int i = 20; ~i; i--) if (val[fa[u][i]] >= l) u = fa[u][i];
        return u;
      }
      inline int getR(int u, int r) {
        for (int i = 20; ~i; i--) if (val[fa[u][i]] <= r) u = fa[u][i];
        return u;
      }
      inline void out() {
        for (int i = 1; i <= n; i++) {
          printf("%d %d %d
    ", st[i], ed[i], val[i]);
        }
      }
    } A, B;
    int rt[maxn * 35], ch[maxn * 35][2], sz[maxn * 35];
    inline void cpy(int o1, int o2) {
      ch[o1][0] = ch[o2][0], ch[o1][1] = ch[o2][1], sz[o1] = sz[o2];
    }
    void modify(int p, int& u, int l, int r) {
      cpy(++cnto, u); sz[u = cnto]++;
      if (l == r) return;
      int mid = (l + r) >> 1;
      if (p <= mid) modify(p, ch[u][0], l, mid);
      else modify(p, ch[u][1], mid + 1, r);
    }
    int query(int ql, int qr, int l, int r, int o1, int o2) {
      if (!(o1 || o2) || ql > r || qr < l) return 0;
      if (ql <= l && r <= qr) return sz[o2] - sz[o1];
      int mid = (l + r) >> 1, res = 0;
      return query(ql, qr, l, mid, ch[o1][0], ch[o2][0]) + query(ql, qr, mid + 1, r, ch[o1][1], ch[o2][1]);
    }
    
    int main() {
      read(n), read(m), read(q);
      for (int i = 1, u, v; i <= m; i++) {
        read(u), read(v), u++, v++;
        e[i] = edge(u, v);
      }
      A.work(0), B.work(1), B.val[0] = inf;
    //  A.out(), B.out();
      for (int i = 1; i <= n; i++) val[A.dfn[i]] = i;
     // return 0;
      for (int i = 1; i <= n; i++) modify(val[B.dfn[i]], rt[i] = rt[i - 1], 1, n);
     // return 0;
      for (int i = 1, S, E, l, r; i <= q; i++) {
        read(S), read(E), read(l), read(r); S++, E++, l++, r++;
        int a = A.getL(S, l), b = B.getR(E, r);
        write(query(A.st[a], A.ed[a], 1, n, rt[B.st[b] - 1], rt[B.ed[b]]) ? 1 : 0, '
    ');
      }
      return Ot(), 0;
    }
    
  • 相关阅读:
    SAP系统和微信集成的系列教程之十:如何在SAP C4C系统里直接回复消息给微信用户
    SAP系统和微信集成的系列教程之九:如何将微信用户发送给微信公众号的内容自动转存到SAP C4C系统
    SAP系统和微信集成的系列教程之八:100行代码在微信公众号里集成地图搜索功能
    漫谈SAP产品里页面上的Checkbox设计与实现系列之一
    一个SAP成都研究院开发工程师的2020年度总结:未知生,焉知死
    Angular form控件原生HTML代码里ng-reflect-form属性和其值的生成时机
    一个SAP成都研究院开发工程师2020年所有文章列表
    SAP系统和微信集成的系列教程之七:使用Redis存储微信用户和公众号的对话记录
    用shell脚本从git上拉取,项目目录下所有各个子项目代码
    shell脚本小计
  • 原文地址:https://www.cnblogs.com/Sai0511/p/11489235.html
Copyright © 2011-2022 走看看