zoukankan      html  css  js  c++  java
  • BZOJ 3514

    给一个n个点m条边的无向图,k次询问只保留编号在[l,r]中的边时图中的联通块个数,强制在线。

    $$n,m,k leq 2 imes 10^5$$

    依次插入边,用LCT维护生成森林。插入第$i$条边时,如果形成环,就把环上编号最小的边删掉,并记$pre_i$为删掉的边的编号。每次查询时,$[l,r]$中$pre_i<l$的边可以将联通块个数-1,反之不行,用主席树维护即可。

    const int MAXN = 200000 + 5, LOG = 25;
    
    struct Input {
      char buf[1 << 25], *s;
      
      Input() {
    #ifdef LOCAL
        freopen("BZOJ3514.in", "r", stdin);
        freopen("BZOJ3514.out", "w", stdout);
    #endif
        fread(s = buf, 1, 1 << 25, stdin);
      }
      
      friend Input &operator>>(Input &io, int &x) {
        x = 0;
        while (!isdigit(*io.s))
          ++ io.s;
        while (isdigit(*io.s))
          x = x * 10 + *io.s ++ - '0';
        return io;
      }
    } cin;
    
    struct LinkCutTree {
      struct Node {
        Node *fa, *ch[2];
        int pre, next, first, last, min;
        bool flip;
        
        Node() {
          fa = ch[0] = ch[1] = NULL;
          pre = next = first = last = min = INF;
          flip = 0;
        }
        
        bool relation() {
          return this == fa->ch[1];
        }
        
        bool is_root() {
          return !fa || (fa->ch[0] != this && fa->ch[1] != this);
        }
        
        void push_up() {
          min = INF;
          if (ch[0]) {
            chkmin(min, pre);
            chkmin(min, ch[0]->min);
            first = ch[0]->first;
          } else {
            first = pre;
          }
          if (ch[1]) {
            chkmin(min, next);
            chkmin(min, ch[1]->min);
            last = ch[1]->last;
          } else {
            last = next;
          }
        }
        
        void push_down() {
          if (flip) {
            FOR(i, 0, 2) {
              if (ch[i]) {
                std::swap(ch[i]->pre, ch[i]->next);
                std::swap(ch[i]->first, ch[i]->last);
                ch[i]->flip ^= 1;
              }
            }
            std::swap(ch[0], ch[1]);
            flip = 0;
          }
        }
      } *node[MAXN];
      
      void make_tree(int n) {
        For(i, 1, n) {
          node[i] = new Node();
        }
      }
      
      void rotate(Node *o) {
        Node *par = o->fa;
        int dir = o->relation();
        par->ch[dir] = o->ch[dir ^ 1];
        if (o->ch[dir ^ 1]) {
          o->ch[dir ^ 1]->fa = par;
        }
        if (!par->is_root()) {
          par->fa->ch[par->relation()] = o;
        }
        o->fa = par->fa;
        par->fa = o;
        o->ch[dir ^ 1] = par;
        par->push_up();
        o->push_up();
      }
      
      void splay(Node *o) {
        static Node *stack[MAXN];
        int top = 0;
        Node *temp = o;
        for (stack[++ top] = temp; !temp->is_root(); temp = temp->fa) {
          stack[++ top] = temp->fa;
        }
        Rep(i, top, 1) {
          stack[i]->push_down();
        }
        for (; !o->is_root(); rotate(o)) {
          if (!o->fa->is_root()) {
            rotate(o->fa->relation() == o->relation() ? o->fa : o);
          }
        }
      }
      
    #define _first(x) ((x) ? x->first : INF)
      void access(Node *o) {
        for (Node *temp = NULL; o; temp = o, o = o->fa) {
          splay(o);
          o->ch[1] = temp;
          if (temp)
            temp->fa = o;
          o->next = _first(temp);
          o->push_up();
        }
      }
      
      void make_root(Node *o) {
        access(o);
        splay(o);
        o->flip = 1;
        std::swap(o->pre, o->next);
        std::swap(o->first, o->last);
      }
      
      Node *find_root(Node *o) {
        access(o);
        splay(o);
        for (o->push_down(); o->ch[0]; o->push_down()) {
          o = o->ch[0];
        }
        splay(o);
        return o;
      }
      
      int query(Node *o, Node *p) {
        make_root(o);
        access(p);
        splay(p);
        return p->min;
      }
      
      void link(Node *o, Node *p, int val) {
        make_root(p);
        p->fa = o;
        p->pre = val;
        p->push_up();
      }
      
      void cut(Node *o, Node *p) {
        make_root(o);
        access(p);
        splay(p);
        p->ch[0] = o->fa = NULL;
        o->next = p->pre = INF;
        p->push_up();
        o->push_up();
      }
    } T;
    
    struct PresidentTree {
      int ch[2][MAXN * LOG], sum[MAXN * LOG], root[MAXN], cnt;
      
      void insert(int &o, int p, int l, int r, int x) {
        o = ++ cnt;
        ch[0][o] = ch[0][p], ch[1][o] = ch[1][p], sum[o] = sum[p] + 1;
        if (l == r) {
          return;
        }
        int mid = (l + r) >> 1;
        if (x <= mid) {
          insert(ch[0][o], ch[0][p], l, mid, x);
        } else {
          insert(ch[1][o], ch[1][p], mid + 1, r, x);
        } 
      }
      
      int query(int o, int p, int l, int r, int x) {
        if (l == r)
          return sum[o] - sum[p];
        int mid = (l + r) >> 1;
        if (x <= mid)
          return query(ch[0][o], ch[0][p], l, mid, x);
        else
          return query(ch[1][o], ch[1][p], mid + 1, r, x) + sum[ch[0][o]] - sum[ch[0][p]];
      }
    } Seg;
    
    struct Edge {
      int from, to;
    } edge[MAXN];
    
    int main() {
      int n, m, k, type;
      cin >> n >> m >> k >> type;
      T.make_tree(n);
      For(i, 1, m) {
        cin >> edge[i].from >> edge[i].to;
        if (edge[i].from == edge[i].to) {
          Seg.insert(Seg.root[i], Seg.root[i - 1], 0, m, i);
          continue;
        }
        if (T.find_root(T.node[edge[i].from]) == T.find_root(T.node[edge[i].to])) {
          int num = T.query(T.node[edge[i].from], T.node[edge[i].to]);
          T.cut(T.node[edge[num].from], T.node[edge[num].to]);
          T.link(T.node[edge[i].from], T.node[edge[i].to], i);
          Seg.insert(Seg.root[i], Seg.root[i - 1], 0, m, num);
        } else {
          T.link(T.node[edge[i].from], T.node[edge[i].to], i);
          Seg.insert(Seg.root[i], Seg.root[i - 1], 0, m, 0);
        }
      }
      int last_ans = 0;
      For(i, 1, k) {
        int l, r;
        cin >> l >> r;
        if (type) {
          l ^= last_ans;
          r ^= last_ans;
        }
        printf("%d
    ", last_ans = n - Seg.query(Seg.root[r], Seg.root[l - 1], 0, m, l - 1));
      }
      return 0;
    }
  • 相关阅读:
    LVS三种模式配置及优点缺点比较
    LVS负载均衡-DR模式
    Nginx反向代理和负载均衡
    LNMP(centos7.6 Nginx1.16 MySQL5.7 PHP7 )
    Nginx常用模块
    表演中的晴天
    迷雾中前行
    mysql Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nona
    npm install -g cnpm --registry=https://registry.npm.taobao.org
    ubuntu16 安装elasticsearch6.3问题
  • 原文地址:https://www.cnblogs.com/sjkmost/p/9825309.html
Copyright © 2011-2022 走看看