HDU 3726 Graph and Queries(平衡二叉树)(2010 Asia Tianjin Regional Contest)
Description
You are given an undirected graph with N vertexes and M edges. Every vertex in this graph has an integer value assigned to it at the beginning. You're also given a sequence of operations and you need to process them as requested. Here's a list of the possible operations that you might encounter:
1) Deletes an edge from the graph.
The format is [D X], where X is an integer from 1 to M, indicating the ID of the edge that you should delete. It is guaranteed that no edge will be deleted more than once.
2) Queries the weight of the vertex with K-th maximum value among all vertexes currently connected with vertex X (including X itself).
The format is [Q X K], where X is an integer from 1 to N, indicating the id of the vertex, and you may assume that K will always fit into a 32-bit signed integer. In case K is illegal, the value for that query will be considered as undefined, and you should return 0 as the answer to that query.
3) Changes the weight of a vertex.
The format is [C X V], where X is an integer from 1 to N, and V is an integer within the range [-106, 106].
The operations end with one single character, E, which indicates that the current case has ended.
For simplicity, you only need to output one real number - the average answer of all queries.
1) Deletes an edge from the graph.
The format is [D X], where X is an integer from 1 to M, indicating the ID of the edge that you should delete. It is guaranteed that no edge will be deleted more than once.
2) Queries the weight of the vertex with K-th maximum value among all vertexes currently connected with vertex X (including X itself).
The format is [Q X K], where X is an integer from 1 to N, indicating the id of the vertex, and you may assume that K will always fit into a 32-bit signed integer. In case K is illegal, the value for that query will be considered as undefined, and you should return 0 as the answer to that query.
3) Changes the weight of a vertex.
The format is [C X V], where X is an integer from 1 to N, and V is an integer within the range [-106, 106].
The operations end with one single character, E, which indicates that the current case has ended.
For simplicity, you only need to output one real number - the average answer of all queries.
Input
There are multiple test cases in the input file. Each case starts with two integers N and M (1 <= N <= 2 * 104, 0 <= M <= 6 * 104), the number of vertexes in the graph. The next N lines describes the initial weight of each vertex (-106 <= weight[i] <= 106). The next part of each test case describes the edges in the graph at the beginning. Vertexes are numbered from 1 to N. The last part of each test case describes the operations to be performed on the graph. It is guaranteed that the number of query operations [Q X K] in each case will be in the range [1, 2 * 105], and there will be no more than 2 * 105 operations that change the values of the vertexes [C X V].
There will be a blank line between two successive cases. A case with N = 0, M = 0 indicates the end of the input file and this case should not be processed by your program.
There will be a blank line between two successive cases. A case with N = 0, M = 0 indicates the end of the input file and this case should not be processed by your program.
Output
For each test case, output one real number � the average answer of all queries, in the format as indicated in the sample output. Please note that the result is rounded to six decimal places.
题目大意:给一个n个点m条边的无向图,有三种询问,分别为删边、询问某子集内第k大权、修改某点权值,问数次询问后,第二种询问的值的平均数
思路:用treap树维护一个强联通分量。离线处理所有询问,先删掉图中将会被删掉的边,从后往前询问,修改权值的询问也要稍作处理。
PS:因为打错一个字母RE了半天……
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdlib> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 const int MAXC = 500010; 8 const int MAXN = 20010; 9 const int MAXM = 60010; 10 11 int key[MAXN], weight[MAXN], child[MAXN][2], size[MAXN]; 12 int stk[MAXN], top, poi_cnt;//not use point 13 14 inline int newNode(int k) { 15 int x = (top ? stk[top--] : ++poi_cnt); 16 key[x] = k; 17 size[x] = 1; 18 weight[x] = rand(); 19 child[x][0] = child[x][1] = 0; 20 return x; 21 } 22 23 inline void update(int &x) { 24 size[x] = size[child[x][0]] + size[child[x][1]] + 1;//size[0]=0 25 } 26 27 inline void rotate(int &x, int t) { 28 int y = child[x][t]; 29 child[x][t] = child[y][t ^ 1]; 30 child[y][t ^ 1] = x; 31 update(x); update(y); 32 x = y; 33 } 34 35 void insert(int &x, int k) { 36 if (x == 0) x = newNode(k); 37 else { 38 int t = (key[x] < k); 39 insert(child[x][t], k); 40 if (weight[child[x][t]] < weight[x]) rotate(x, t); 41 } 42 update(x); 43 } 44 45 void remove(int &x, int k) { 46 if(key[x] == k) { 47 if(child[x][0] && child[x][1]) { 48 int t = weight[child[x][0]] < weight[child[x][1]]; 49 rotate(x, t); remove(child[x][t ^ 1], k); 50 } 51 else { 52 stk[++top] = x; 53 x = child[x][0] + child[x][1]; 54 } 55 } 56 else remove(child[x][key[x] < k], k); 57 if(x > 0) update(x); 58 } 59 60 struct Command { 61 char type; 62 int x, p; 63 } commands[MAXC]; 64 65 int n, m, value[MAXN], from[MAXM], to[MAXM], removed[MAXM]; 66 67 int fa[MAXN]; 68 int getfather(int x) { 69 if(fa[x] == x) return x; 70 else return fa[x] = getfather(fa[x]); 71 } 72 73 int root[MAXN]; 74 75 void mergeto(int &x, int &y) { 76 if(child[x][0]) mergeto(child[x][0], y); 77 if(child[x][1]) mergeto(child[x][1], y); 78 insert(y, key[x]); 79 stk[++top] = x; 80 } 81 82 inline void addEdge(int x) { 83 int u = getfather(from[x]), v = getfather(to[x]); 84 if(u != v) { 85 if(size[root[u]] > size[root[v]]) swap(u, v); 86 fa[u] = v; mergeto(root[u], root[v]); 87 } 88 } 89 90 int kth(int &x, int k) { 91 if(x == 0 || k <= 0 || k > size[x]) return 0; 92 int s = 0; 93 if(child[x][1]) s = size[child[x][1]]; 94 if(k == s + 1) return key[x]; 95 if(k <= s) return kth(child[x][1], k); 96 return kth(child[x][0], k - s - 1); 97 } 98 99 int query_cnt; 100 long long query_tot; 101 102 void query(int x, int k) { 103 ++query_cnt; 104 query_tot += kth(root[getfather(x)], k); 105 } 106 107 inline void change_value(int x, int v) { 108 int u = getfather(x); 109 remove(root[u], value[x]); 110 insert(root[u], value[x] = v); 111 } 112 113 int main() { 114 int kase = 0; 115 size[0] = 0; 116 while(scanf("%d%d", &n, &m) != EOF && n) { 117 for(int i = 1; i <= n; ++i) scanf("%d", &value[i]); 118 for(int i = 1; i <= m; ++i) scanf("%d%d", &from[i], &to[i]); 119 memset(removed, 0, sizeof(removed)); 120 121 int c = 0; 122 while(true) { 123 char type; 124 int x, p = 0, v = 0; 125 scanf(" %c", &type); 126 if(type == 'E') break; 127 scanf("%d", &x); 128 if(type == 'D') removed[x] = 1; 129 if(type == 'Q') scanf("%d", &p); 130 if(type == 'C') { 131 scanf("%d", &v); 132 p = value[x]; 133 value[x] = v; 134 } 135 commands[c++] = (Command) {type, x, p}; 136 } 137 138 top = poi_cnt = 0; 139 for(int i = 1; i <= n; ++i) { 140 fa[i] = i; 141 root[i] = newNode(value[i]); 142 } 143 for(int i = 1; i <= m; ++i) if(!removed[i]) addEdge(i); 144 145 query_tot = query_cnt = 0; 146 for(int i = c - 1; i >= 0; --i) { 147 if(commands[i].type == 'D') addEdge(commands[i].x); 148 if(commands[i].type == 'Q') query(commands[i].x, commands[i].p); 149 if(commands[i].type == 'C') change_value(commands[i].x, commands[i].p); 150 } 151 printf("Case %d: %.6f\n", ++kase, query_tot/(double)query_cnt); 152 } 153 return 0; 154 }