• BZOJ4399 魔法少女LJJ【线段树合并】【并查集】


    Description

    在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了
    LJJ感叹道“这里真是个迷人的绿色世界,空气清新、淡雅,到处散发着醉人的奶浆味;小猴在枝头悠来荡去,好不自在;各式各样的鲜花争相开放,各种树枝的枝头挂满沉甸甸的野果;鸟儿的歌声婉转动听,小河里飘着落下的花瓣真是人间仙境”
    SHY觉得LJJ还是太naive,一天,SHY带着自己心爱的图找到LJJ,对LJJ说:“既然你已经见识过动态树,动态仙人掌了,那么今天就来见识一下动态图吧”
    LJJ:“要支持什么操作?”
    SHY:“
    1.新建一个节点,权值为x。
    2.连接两个节点。
    3.将一个节点a所属于的联通快内权值小于x的所有节点权值变成x。
    4.将一个节点a所属于的联通快内权值大于x的所有节点权值变成x。
    5.询问一个节点a所属于的联通块内的第k小的权值是多少。
    6.询问一个节点a所属联通快内所有节点权值之积与另一个节点b所属联通快内所有节点权值之积的大小。
    7.询问a所在联通快内节点的数量
    8.若两个节点a,b直接相连,将这条边断开。
    9.若节点a存在,将这个点删去。

    LJJ:“我可以离线吗?”
    SHY:“可以,每次操作是不加密的,”
    LJJ:“我可以暴力吗?”
    SHY:“自重”
    LJJ很郁闷,你能帮帮他吗

    Input

    第一行有一个正整数m,表示操作个数。
    接下来m行,每行先给出1个正整数c。
    若c=1,之后一个正整数x,表示新建一个权值为x的节点,并且节点编号为n+1(当前有n个节点)。
    若c=2,之后两个正整数a,b,表示在a,b之间连接一条边。
    若c=3,之后两个正整数a,x,表示a联通快内原本权值小于x的节点全部变成x。
    若c=4,之后两个正整数a,x,表示a联通快内原本权值大于x的节点全部变成x。
    若c=5,之后两个正整数a,k,表示询问a所属于的联通块内的第k小的权值是多少。
    若c=6,之后两个正整数a,b,表示询问a所属联通快内所有节点权值之积与b所属联通快内所有节点权值之积的大小,
    若a所属联通快内所有节点权值之积大于b所属联通快内所有节点权值之积,输出1,否则为0。
    若c=7,之后一个正整数a,表示询问a所在联通块大小
    若c=8,之后两个正整数a,b,表示断开a,b所连接的边。
    若c=9,之后一个正整数a,表示断开a点的所有连边
    具体输出格式见样例

    Output

    Sample Input

    12
    1 2
    1 3
    1 4
    1 5
    1 6
    2 1 2
    2 2 3
    2 3 4
    2 4 5
    9 1
    3 2 5
    5 3 4

    Sample Output

    6

    HINT

    对100%的数据 0<=m<=400000,c<=7,所有出现的数均<=1000000000,所有出现的点保证存在
    【HINT】请认真阅读题面


    思路

    (cle 7)
    神不神奇?

    所以就只用并查集维护联通关系然后线段树合并就可以了

    这题比较卡空间

    值域线段树需要离散化一下

    把区间max min 变成区间赋值成0和单点加就可以了

    其他的都是常规操作


    //Author: dream_maker
    #include<bits/stdc++.h>
    using namespace std;
    //----------------------------------------------
    //typename
    typedef long long ll;
    //convenient for
    #define fu(a, b, c) for (int a = b; a <= c; ++a)
    #define fd(a, b, c) for (int a = b; a >= c; --a)
    #define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
    //inf of different typename
    const int INF_of_int = 1e9;
    const ll INF_of_ll = 1e18;
    //fast read and write
    bool w;char c;
    template <typename T>
    void Read(T &x) {
      w = 1;x = 0;
      c = getchar();
      while (!isdigit(c) && c != '-') c = getchar();
      if (c == '-') w = 0, c = getchar();
      while (isdigit(c)) {
        x = (x<<1) + (x<<3) + c -'0';
        c = getchar();
      }
      if (!w) x = -x;
    }
    template <typename T>
    void Write(T x) {
      if (x < 0) {
        putchar('-');
        x = -x; 
      }
      if (x > 9) Write(x / 10);
      putchar(x % 10 + '0');
    }
    //----------------------------------------------
    const int M = 4e5 + 10;
    const int N = M * 18;
    struct Ques{
      int op, x, y;
    } q[M];
    int pre[M], tot = 0;
    int cnt = 0, ind = 0;
    int rt[M], fa[M];
    int ls[N], rs[N], siz[N];
    bool cl[N];
    double sum[N];
    void pushup(int t) {
      siz[t] = siz[ls[t]] + siz[rs[t]];
      sum[t] = sum[ls[t]] + sum[rs[t]];
    }
    void pushnow(int t) {
      siz[t] = sum[t] = 0;
      cl[t] = 1;
    }
    void pushdown(int t) {
      if (cl[t]) {
        if (ls[t]) pushnow(ls[t]);
        if (rs[t]) pushnow(rs[t]);
        cl[t] = 0;
      }
    }
    void insert(int &t, int l, int r, int pos, double vl, int num) {
      if (!t) t = ++cnt;
      if (l == r) {
        sum[t] += vl * (double)num;
        siz[t] += num;
        return;
      }
      pushdown(t);
      int mid = (l + r) >> 1;
      if (pos <= mid) insert(ls[t], l, mid, pos, vl, num);
      else insert(rs[t], mid + 1, r, pos, vl, num);
      pushup(t);
    }
    bool check(int t) {
      return !ls[t] && !rs[t];
    }
    int merge(int x, int y) {
      if (!x || !y) return x + y;
      siz[x] += siz[y];
      sum[x] += sum[y];
      pushdown(x), pushdown(y);
      ls[x] = merge(ls[x], ls[y]);
      rs[x] = merge(rs[x], rs[y]);
      return x;
    }
    void modify(int t, int l, int r, int ql, int qr) {
      if (!t) return;
      if(ql <= l && r <= qr) {
        pushnow(t);
        return;
      }
      pushdown(t);
      int mid = (l + r) >> 1;
      if (qr <= mid) modify(ls[t], l, mid, ql, qr);
      else if (ql > mid) modify(rs[t], mid + 1, r, ql, qr);
      else {
        modify(ls[t], l, mid, ql, mid);
        modify(rs[t], mid + 1, r, mid + 1, qr);
      } 
      pushup(t);
    }
    int query(int t, int l, int r, int ql, int qr) {
      if (!t || ql > qr) return 0;
      if (ql <= l && r <= qr) return siz[t];
      pushdown(t);
      int mid = (l + r) >> 1;
      if (qr <= mid) return query(ls[t], l, mid, ql, qr);
      else if(ql > mid) return query(rs[t], mid + 1, r, ql, qr);
      else return query(ls[t], l, mid, ql, mid) + query(rs[t], mid + 1, r, mid + 1, qr);
    }
    int kth(int t, int l, int r, int k) {
      if (l == r) return l;
      pushdown(t);
      int mid = (l + r) >> 1;
      if (k <= siz[ls[t]]) return kth(ls[t], l, mid, k);
      else return kth(rs[t], mid + 1, r, k - siz[ls[t]]);
    }
    int find(int x) {
      return fa[x] == x ? x : fa[x] = find(fa[x]);
    }
    void solve1(Ques t) {
      int nowx = lower_bound(pre + 1, pre + tot + 1, t.x) - pre;
      insert(rt[++ind], 1, tot, nowx, log2(t.x), 1);
      fa[ind] = ind;
    }
    void solve2(Ques t) {
      t.x = find(t.x), t.y = find(t.y);
      if (t.x == t.y) return;
      fa[t.x] = t.y;
      rt[t.y] = merge(rt[t.x], rt[t.y]);
    }
    void solve3(Ques t) {
      t.x = find(t.x);
      int nowy = lower_bound(pre + 1, pre + tot + 1, t.y) - pre;
      int s = query(rt[t.x], 1, tot, 1, nowy - 1);
      modify(rt[t.x], 1, tot, 1, nowy - 1);
      insert(rt[t.x], 1, tot, nowy, log2(t.y), s);
    }
    void solve4(Ques t) {
      t.x = find(t.x);
      int nowy = lower_bound(pre + 1, pre + tot + 1, t.y) - pre;
      int s = query(rt[t.x], 1, tot, nowy + 1, tot);
      modify(rt[t.x], 1, tot, nowy + 1, tot);
      insert(rt[t.x], 1, tot, nowy, log2(t.y), s);
    }
    void solve5(Ques t) {
      t.x = find(t.x);
      Write(pre[kth(rt[t.x], 1, tot, t.y)]);
      putchar('
    ');
    }
    void solve6(Ques t) {
      t.x = find(t.x), t.y = find(t.y);
      if (sum[rt[t.x]] > sum[rt[t.y]]) printf("1
    ");
      else printf("0
    ");
    }
    void solve7(Ques t) {
      t.x = find(t.x);
      Write(siz[rt[t.x]]); putchar('
    ');
    }
    int main() {
    #ifdef dream_maker
      freopen("input.txt", "r", stdin);
    #endif
      int m;Read(m);
      fu(i, 1, m) {
        Read(q[i].op);
        if (q[i].op == 1 || q[i].op == 7) Read(q[i].x);
        else Read(q[i].x), Read(q[i].y);
        if (q[i].op == 1) pre[++tot] = q[i].x;
        if (q[i].op == 3 || q[i].op == 4) pre[++tot] = q[i].y;
      }
      sort(pre + 1, pre + tot + 1);
      tot = unique(pre + 1, pre + tot + 1) - pre - 1;
      fu(i, 1, m) {
        if (q[i].op == 1) solve1(q[i]);
        if (q[i].op == 2) solve2(q[i]);
        if (q[i].op == 3) solve3(q[i]);
        if (q[i].op == 4) solve4(q[i]);
        if (q[i].op == 5) solve5(q[i]);
        if (q[i].op == 6) solve6(q[i]);
        if (q[i].op == 7) solve7(q[i]);
      }
      return 0;
    }
    
  • 相关阅读:
    Webpack 打包 14. html压缩
    webpack优化环境配置 18.HMR
    Webpack 打包 10. 压缩CSS
    Wenpack 打包 15. 生产环境配置(提取JS中的CSS、压缩CSS、压缩html、eslint语法检查...)
    Webpack 打包 13. 压缩JS
    webpack优化环境配置 17.优化配置介绍
    Webpack 打包 11. eslint 语法检查
    AtCoder Beginner Contest 258
    AtCoder Beginner Contest 259
    AtCoder Beginner Contest 261
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9777302.html
Copyright © 2020-2023  润新知