数据结构C
Time Limit: 20 Sec Memory Limit: 512 MBDescription
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 }
- [提交][状态][讨论]