【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\n", Ans[i] - Base);
154 }
View Code

 

  • [提交][状态][讨论]
posted @ 2017-10-13 21:54  BearChild  阅读(269)  评论(0编辑  收藏  举报