题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3726
题意:n个点m条边的一张无向图,每个点有一个权值, 有3中操作。
D X 删除第X条边
Q X K 计算与X点相连所有点中第k大的权值
C X V把X的权值改为 V
输出 Q次询问的平均值
大白上的例题, 离线处理,把所有操作 反过来处理,,这样删边变成了 加边,,瞬间好处理多了。。细节也有很多。
1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 typedef unsigned long long ull; 16 typedef long long ll; 17 const int inf = 0x3f3f3f3f; 18 const double eps = 1e-8; 19 const int maxn = 2e4+10; 20 int n, m, val[maxn]; 21 int pa[maxn]; 22 void init() 23 { 24 for (int i = 0; i <= n; i++) 25 { 26 pa[i] = i; 27 } 28 } 29 int find(int x) 30 { 31 return pa[x] = (pa[x] == x ? x : find(pa[x])); 32 } 33 struct Node 34 { 35 Node* ch[2]; 36 int key, r, siz; 37 Node (int x) 38 { 39 key = x; 40 siz = 1; 41 ch[0] = ch[1] = NULL; 42 r = rand(); 43 } 44 bool operator < (const Node &rhs)const 45 { 46 return r < rhs.r; 47 } 48 int cmp(int x) 49 { 50 if (x == key) 51 return -1; 52 return x < key ? 0 : 1; 53 } 54 void maintain() 55 { 56 siz = 1; 57 if (ch[0] != NULL) 58 siz += ch[0] -> siz; 59 if (ch[1] != NULL) 60 siz += ch[1] -> siz; 61 } 62 }; 63 void rotate(Node* &root, int d) 64 { 65 Node* tmp = root -> ch[d^1]; 66 root -> ch[d^1] = tmp -> ch[d]; 67 tmp -> ch[d] = root; 68 root -> maintain(); 69 tmp -> maintain(); 70 root = tmp; 71 } 72 void insert(Node* &root, int x) 73 { 74 if (root == NULL) 75 root = new Node (x); 76 else 77 { 78 int d = x < root -> key ? 0 : 1; 79 insert (root ->ch[d], x); 80 if (root -> ch[d] -> r > root -> r) 81 rotate(root, d^1); 82 83 } 84 root -> maintain(); 85 } 86 void dele(Node* &root, int x) 87 { 88 int d = root -> cmp(x); 89 if (d == -1) 90 { 91 Node* tmp = root; 92 if (root -> ch[0] != NULL && root -> ch[1] != NULL) 93 { 94 int d1 = (root -> ch[0] -> r > root -> ch[1] -> r ? 0 : 1); 95 rotate(root, d1^1); 96 dele(root -> ch[d1^1], x); 97 } 98 else 99 { 100 if (root -> ch[0] == NULL) 101 root = root -> ch[1]; 102 else 103 root = root -> ch[0]; 104 delete tmp; 105 } 106 } 107 else 108 dele(root->ch[d], x); 109 if (root != NULL) 110 root -> maintain(); 111 } 112 int Get_kth(Node* root, int k) 113 { 114 if (root == NULL || k <= 0 || root -> siz < k) 115 return 0; 116 int s = root -> ch[1] == NULL ? 0 : root -> ch[1] -> siz; 117 if (s + 1 == k) 118 return root -> key; 119 if (s + 1 > k) 120 return Get_kth(root -> ch[1], k); 121 else 122 return Get_kth(root -> ch[0], k-s-1); 123 124 } 125 Node* root[maxn]; 126 void merge_tree(Node* &src, Node* &fa) 127 { 128 if (src -> ch[0] != NULL) 129 merge_tree(src -> ch[0], fa); 130 if (src -> ch[1] != NULL) 131 merge_tree(src -> ch[1], fa); 132 insert(fa, src -> key); 133 delete src; 134 src = NULL; 135 } 136 void remove_tree(Node* &root) 137 { 138 if (root -> ch[0] != NULL) 139 remove_tree(root -> ch[0]); 140 if (root -> ch[1] != NULL) 141 remove_tree(root -> ch[1]); 142 delete root; 143 root = NULL; 144 } 145 struct 146 { 147 int x, y; 148 bool is_del; 149 } e[3 * maxn]; 150 struct 151 { 152 int type, x, p; 153 } Q[maxn*25]; 154 void add_edge(int idx) 155 { 156 int fx = find(e[idx].x); 157 int fy = find(e[idx].y); 158 if (fx != fy) 159 { 160 if (root[fx] -> siz > root[fy] -> siz) 161 { 162 pa[fy] = fx; 163 merge_tree(root[fy], root[fx]); 164 } 165 else 166 { 167 pa[fx] = fy; 168 merge_tree(root[fx], root[fy]); 169 170 } 171 } 172 173 } 174 int main(void) 175 { 176 #ifndef ONLINE_JUDGE 177 freopen("in.txt","r",stdin); 178 #endif 179 int cas = 1; 180 while (~ scanf ("%d%d",&n, &m)) 181 { 182 if (n == 0 && m == 0) 183 break; 184 for (int i = 0; i < n; i++) 185 { 186 scanf ("%d", val + 1 + i); 187 } 188 for (int i = 1; i <= m; i++) 189 { 190 scanf ("%d%d", &e[i].x, &e[i].y); 191 e[i].is_del = false; 192 } 193 char op[5]; 194 int tot = 0; 195 while (scanf ("%s",op) && op[0] != 'E') 196 { 197 if (op[0] == 'D') 198 { 199 scanf ("%d", &Q[tot].x); 200 Q[tot++].type = 0; 201 e[Q[tot-1].x].is_del = true; 202 } 203 if (op[0] == 'Q') 204 { 205 scanf ("%d%d", &Q[tot].x, &Q[tot].p); 206 Q[tot++].type = 1; 207 } 208 if (op[0] == 'C') 209 { 210 int v; 211 scanf ("%d%d", &Q[tot].x, &v); 212 Q[tot].p = val[Q[tot].x]; 213 val[Q[tot].x] = v; 214 Q[tot++].type = 2; 215 } 216 } 217 init(); 218 for (int i = 0; i < n; i++) 219 { 220 if (root[i+1] != NULL) 221 remove_tree(root[i+1]); 222 root[i+1] = new Node (val[i+1]); 223 } 224 for (int i = 0; i < m; i++) 225 { 226 if (e[i+1].is_del == false) 227 add_edge(i+1); 228 } 229 ll ans1 = 0, ans2 = 0; 230 for (int i = tot - 1; i >= 0; i--) 231 { 232 if (Q[i].type == 0) 233 { 234 add_edge(Q[i].x); 235 } 236 if (Q[i].type == 1) 237 { 238 ans1 += Get_kth(root[find(Q[i].x)], Q[i].p); 239 ans2 ++; 240 } 241 if (Q[i].type == 2) 242 { 243 int father = find(Q[i].x); 244 dele (root[father], val[Q[i].x]); 245 insert (root[father], Q[i].p); 246 val[Q[i].x] = Q[i].p; 247 } 248 } 249 printf("Case %d: %.6f ", cas++, 1.0*ans1 / ans2); 250 } 251 return 0; 252 }