• 【Foreign】数据结构C [线段树]


    数据结构C

    Time Limit: 20 Sec  Memory Limit: 512 MB

    Description

      

    Input

      

    Output

      

    Sample Input

      

    Sample Output

      

    HINT

      

    Solution

      首先,D操作为删除操作显然不可做,又发现这道题可以离线处理,那么我们考虑倒着来,维护加入操作。

      那么这时候,D操作就变为了合并操作,那么这时候我们只需要维护一个:可以支持单点修改查询第 k 大信息可合并的数据结构即可。

      显然构建若干棵权值线段树即可!对于每个联通块维护一棵线段树,用并查集判断两点是否在一个块内。

      这时候,D操作显然判断一下两点是否在一个联通块内,不在则合并两棵线段树;Q操作就是查询第 k 大,在树上二分即可;C操作就是原来值个数-1新加入值个数+1

      就简单地解决了这题啦!(本质上就是BZOJ1926弱化 + BZOJ1015 QWQ

    Code

      1 #include<iostream>  
      2 #include<algorithm>  
      3 #include<cstdio>  
      4 #include<cstring>  
      5 #include<cstdlib>  
      6 #include<cmath>  
      7 using namespace std;
      8    
      9 const int ONE = 1000005;
     10 const int INF = 2e6;
     11 const int Base = 1e6;
     12 
     13 int n, m;
     14 int opt, x, val;
     15 int Val[100005];
     16 char s[5];
     17 
     18 int Ans[300005], ans_num = 0;
     19 
     20 int fat[100005];
     21 
     22 int Num = 0, del[100005];
     23 struct power {int opt, x, val;} oper[ONE];
     24 struct point {int x, y;} a[100005];
     25 int total = 0;
     26 struct seg
     27 {
     28         int root;
     29         int left, right;
     30         int val;
     31 }Node[ONE * 4];
     32 
     33 int get()
     34 {
     35         int res=1,Q=1;    char c;
     36         while( (c=getchar())<48 || c>57)
     37         if(c=='-')Q=-1;
     38         if(Q) res=c-48; 
     39         while((c=getchar())>=48 && c<=57) 
     40         res=res*10+c-48; 
     41         return res*Q; 
     42 }
     43 
     44 int Find(int x)
     45 {
     46         if(fat[x] == x) return x;
     47         return fat[x] = Find(fat[x]);
     48 }
     49 
     50 void Un(int x, int y)
     51 {
     52         int f1 = Find(x), f2 = Find(y);
     53         if(f1 != f2) fat[f1] = f2;
     54 }
     55 
     56 void Update(int &i, int l, int r, int Val, int opt) //pos = Val , + opt
     57 {
     58         if(!i) i = ++total;
     59         
     60         Node[i].val = Node[i].val + opt;
     61         
     62         if(l == r) return;
     63         int mid = l + r >> 1;
     64         
     65         if(Val <= mid) Update(Node[i].left, l, mid, Val, opt);
     66         else Update(Node[i].right, mid + 1, r, Val, opt);
     67         
     68 }
     69 
     70 int Merge(int y, int x) //y merge to x
     71 {
     72         if(x == 0 || y == 0) return x + y;
     73         
     74         Node[x].val += Node[y].val;
     75         Node[x].left =  Merge(Node[x].left, Node[y].left);
     76         Node[x].right = Merge(Node[x].right, Node[y].right);
     77     
     78         return x;
     79 }
     80 
     81 int Query(int i, int l, int r, int k) //k da
     82 {
     83         if(l == r) return l;
     84         int mid = l + r >> 1, Val = Node[ Node[i].right ].val;
     85         
     86         if(k > Val)
     87             return Query(Node[i].left, l, mid, k - Val);
     88         else
     89             return Query(Node[i].right, mid + 1, r, k);
     90 }
     91 
     92 void Deal_first()
     93 {
     94         for(int i = 1; i <= n; i++)
     95             fat[i] = i, Node[i].root = ++total;
     96         for(int i = 1; i <= m; i++)
     97             if(del[i] != 1) Un(a[i].x, a[i].y);
     98         for(int i = 1; i <= n; i++)
     99             Update(Node[Find(i)].root, 0, INF, Val[i], 1);
    100 }
    101 
    102 void Deal_add(int x, int y)
    103 {
    104         x = Find(x), y = Find(y);
    105         if(x == y) return;
    106         Merge(Node[x].root, Node[y].root);
    107         fat[x] = y;
    108 }
    109 
    110 void Deal_query(int root, int k)
    111 {
    112         root = Find(root);
    113         if(Node[root].val < k) {Ans[++ans_num] = 0 + Base; return;}
    114         Ans[++ans_num] = Query(Node[root].root, 0, INF, k);
    115 }
    116 
    117 void Deal_change(int x, int y) //x is point, y is need val
    118 {
    119         int root = Find(x);
    120         Update(Node[root].root, 0, INF, Val[x], -1);
    121         Update(Node[root].root, 0, INF, y, 1);
    122         Val[x] = y;
    123 }
    124 
    125 int main()
    126 {
    127         n = get();    m = get();
    128         
    129         for(int i = 1; i <= n; i++) Val[i] = get() + Base;
    130         for(int i = 1; i <= m; i++)
    131             a[i].x = get(), a[i].y = get();
    132         for(;;)
    133         {
    134             scanf("%s", s);
    135             if(s[0] == 'E') break;
    136             if(s[0] == 'D')
    137                 x = get(), del[x] = 1, oper[++Num] = (power){1, x, 0};
    138             if(s[0] == 'Q')
    139                 x = get(), val = get(), oper[++Num] = (power){2, x, val};
    140             if(s[0] == 'C')
    141                 x = get(), val = get(), oper[++Num] = (power){3, x, Val[x]}, Val[x] = val + Base;
    142         }
    143         
    144         Deal_first();
    145         for(int i = Num; i >= 1; i--)
    146         {
    147             if(oper[i].opt == 1) Deal_add(a[ oper[i].x ].x, a[ oper[i].x ].y);
    148             if(oper[i].opt == 2) Deal_query(oper[i].x, oper[i].val);
    149             if(oper[i].opt == 3) Deal_change(oper[i].x, oper[i].val);
    150         }
    151         
    152         for(int i = ans_num; i >= 1; i--)
    153             printf("%d
    ", Ans[i] - Base);
    154 }
    View Code
    • [提交][状态][讨论]
  • 相关阅读:
    shell脚本编程入门
    正则表达式
    201871010116祁英红《面向对象程序设计(java)》第七周学习总结
    201871010116祁英红《面向对象程序设计(java)》第八周学习总结
    201871010116祁英红《面向对象程序设计(java)》第十一周学习总结
    201871010116祁英红《面向对象程序设计(java)》第67周学习总结
    201871010116祁英红《面向对象程序设计(java)》第十二周学习总结
    201871010116祁英红《面向对象程序设计(java)》第一周学习总结
    201871010116祁英红《面向对象程序设计(java)》第二周学习总结
    201871010116祁英红《面向对象程序设计(java)》第十周学习总结
  • 原文地址:https://www.cnblogs.com/BearChild/p/7663495.html
Copyright © 2020-2023  润新知