2015-03-16 19:52:57
思路:一道比较裸的插入不断插入数值、删除数值 + 查询第k大的题目。
(1)对于合并操作,可以采用并查集来维护,并维护一个num值来表示group总数。
(2)对于查询第k大的操作
(i)可以用树状数组维护+二分查找来不断逼近第k大
(ii)可以利用树状数组本身c[]数组的特性来倍增逼近第k大
(iii)用treap来查询第k大
(iv)当然还可以用线段树.....
方法1:树状数组+二分
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <string> 11 #include <iostream> 12 #include <algorithm> 13 using namespace std; 14 15 #define MEM(a,b) memset(a,b,sizeof(a)) 16 #define REP(i,n) for(int i=1;i<=(n);++i) 17 #define REV(i,n) for(int i=(n);i>=1;--i) 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 20 #define getmid(l,r) ((l) + ((r) - (l)) / 2) 21 #define MP(a,b) make_pair(a,b) 22 23 typedef long long ll; 24 typedef pair<int,int> pii; 25 const int INF = (1 << 30) - 1; 26 const int MAXN = 300010; 27 28 int N,M,num; 29 int fa[MAXN],sz[MAXN]; 30 31 struct BIT{ 32 int c[MAXN]; 33 int Lowbit(int x){ 34 return x & (-x); 35 } 36 void clear(){ 37 MEM(c,0); 38 } 39 void Update(int x,int d){ 40 while(x <= N){ 41 c[x] += d; 42 x += Lowbit(x); 43 } 44 } 45 int Getsum(int x){ 46 int res = 0; 47 while(x){ 48 res += c[x]; 49 x -= Lowbit(x); 50 } 51 return res; 52 } 53 }bt; 54 55 int Find(int x){ 56 return fa[x] == x ? x : fa[x] = Find(fa[x]); 57 } 58 59 int main(){ 60 int a,b,c,k; 61 scanf("%d%d",&N,&M); 62 bt.Update(1,N); 63 REP(i,N) fa[i] = i,sz[i] = 1; 64 num = N; 65 REP(i,M){ 66 scanf("%d",&c); 67 if(c == 0){ 68 scanf("%d%d",&a,&b); 69 int x = Find(a); 70 int y = Find(b); 71 if(x == y) continue; 72 bt.Update(sz[x],-1); 73 bt.Update(sz[y],-1); 74 fa[x] = y; 75 sz[y] += sz[x]; 76 bt.Update(sz[y],1); 77 num--; 78 } 79 else{ 80 scanf("%d",&k); 81 k = num + 1 - k; 82 int l = 1,r = N; 83 while(l <= r){ 84 int mid = (l + r) / 2; //getmid(l,r); 85 if(bt.Getsum(mid) >= k) r = mid - 1; 86 else l = mid + 1; 87 } 88 printf("%d\n",l); 89 } 90 } 91 return 0; 92 }