Graph and Queries
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1467 Accepted Submission(s): 301
Problem 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 [-10
6, 10
6].
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 * 10
4, 0 <= M <= 6 * 10
4), the number of vertexes in the graph. The next N lines describes the initial weight of each vertex (-106 <= weight[i] <= 10
6). 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 * 10
5], and there will be no more than 2 * 10
5 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.
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.
Sample Input 3 3 10 20 30 1 2 2 3 1 3 D 3 Q 1 2 Q 2 1 D 2 Q 3 2 C 1 50 Q 1 1 E 3 3 10 20 20 1 2 2 3 1 3 Q 1 1 Q 1 2 Q 1 3 E 0 0
Sample Output Case 1: 25.000000 Case 2: 16.666667
Hint For the first sample: D 3 — deletes the 3rd edge in the graph (the remaining edges are (1, 2) and (2, 3)) Q 1 2 — finds the vertex with the second largest value among all vertexes connected with 1. The answer is 20. Q 2 1 — finds the vertex with the largest value among all vertexes connected with 2. The answer is 30. D 2 — deletes the 2nd edge in the graph (the only edge left after this operation is (1, 2)) Q 3 2 — finds the vertex with the second largest value among all vertexes connected with 3. The answer is 0 (Undefined). C 1 50 — changes the value of vertex 1 to 50. Q 1 1 — finds the vertex with the largest value among all vertex connected with 1. The answer is 50. E — This is the end of the current test case. Four queries have been evaluated, and the answer to this case is (20 + 30 + 0 + 50) / 4 = 25.000. For the second sample, caution about the vertex with same weight: Q 1 1 – the answer is 20 Q 1 2 – the answer is 20 Q 1 3 – the answer is 10
Source
2010 Asia Tianjin Regional Contest
Recommend zhouzeyong
题目首先给出了N个点,M条边的图。每个点有一个对应的权值。
然后下面由三种操作:
1: D X :删掉第X条边。
2: Q X K :查询和X相连的点中 第K大的点的值(K=1表示最大,K=2表示第二大,。。。。)
3: C X V :将点X的权值修改为V
离线处理。
点的权值的变化使用邻接表存下来。
离线后删边当成加边,就是合并。
合并的时候只能把点的个数少的一个个插入
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013/8/28 23:05:49 4 File Name :F:\2013ACM练习\专题学习\splay_tree_2\HDU3726.cpp 5 ************************************************ */ 6 7 #include <stdio.h> 8 #include <string.h> 9 #include <iostream> 10 #include <algorithm> 11 #include <vector> 12 #include <queue> 13 #include <set> 14 #include <map> 15 #include <string> 16 #include <math.h> 17 #include <stdlib.h> 18 #include <time.h> 19 using namespace std; 20 21 #define Key_value ch[ch[root][1]][0] 22 const int MAXN = 20010; 23 int pre[MAXN],ch[MAXN][2],key[MAXN],size[MAXN]; 24 int root; 25 26 void NewNode(int &r,int father,int loc,int k) 27 { 28 r = loc; 29 pre[r] = father; 30 ch[r][0] = ch[r][1] = 0; 31 key[r] = k; 32 size[r] = 1; 33 } 34 void push_up(int r) 35 { 36 size[r] = size[ch[r][0]] + size[ch[r][1]] + 1; 37 } 38 39 void Init() 40 { 41 root = 0; 42 ch[root][0] = ch[root][1] = key[root] = size[root] = 0; 43 pre[root] = 0; 44 } 45 46 void Rotate(int x,int kind) 47 { 48 int y = pre[x]; 49 ch[y][!kind] = ch[x][kind]; 50 pre[ch[x][kind]] = y; 51 if(pre[y]) 52 ch[pre[y]][ch[pre[y]][1]==y] = x; 53 pre[x] = pre[y]; 54 ch[x][kind] = y; 55 pre[y] = x; 56 push_up(y); 57 } 58 void Splay(int r,int goal) 59 { 60 while(pre[r] != goal) 61 { 62 if(pre[pre[r]] == goal) 63 Rotate(r,ch[pre[r]][0] == r); 64 else 65 { 66 int y = pre[r]; 67 int kind = ch[pre[y]][0]==y; 68 if(ch[y][kind] == r) 69 { 70 Rotate(r,!kind); 71 Rotate(r,kind); 72 } 73 else 74 { 75 Rotate(y,kind); 76 Rotate(r,kind); 77 } 78 } 79 } 80 push_up(r); 81 if(goal == 0) root = r; 82 } 83 int Get_kth(int r,int k) 84 { 85 int t = size[ch[r][0]] + 1; 86 if(t == k)return r; 87 if(t > k)return Get_kth(ch[r][0],k); 88 else return Get_kth(ch[r][1],k-t); 89 } 90 91 void Insert(int loc,int k) 92 { 93 int r = root; 94 if(r == 0) 95 { 96 NewNode(root,0,loc,k); 97 return; 98 } 99 while(ch[r][key[r]<k]) 100 r = ch[r][key[r]<k]; 101 NewNode(ch[r][key[r]<k],r,loc,k); 102 Splay(ch[r][key[r]<k],0); 103 } 104 105 106 struct Edge 107 { 108 int u,v; 109 }edge[60010]; 110 bool used[60010]; 111 112 //把修改的值建成邻接表 113 int to[400010]; 114 int next[400010]; 115 int head[20010]; 116 int tot; 117 118 void add_value(int x,int v) 119 { 120 to[tot] = v; 121 next[tot] = head[x]; 122 head[x] = tot++; 123 } 124 125 struct Query 126 { 127 char op[5]; 128 int x,y; 129 }query[400010]; 130 int q_num; 131 132 int F[20010]; 133 134 int find(int x) 135 { 136 if(F[x] == -1)return x; 137 else return F[x] = find(F[x]); 138 } 139 140 void erase(int r) 141 { 142 if(!r)return; 143 erase(ch[r][0]); 144 erase(ch[r][1]); 145 Insert(r,to[head[r]]); 146 } 147 int Get_Min(int r) 148 { 149 while(ch[r][0]) 150 { 151 r = ch[r][0]; 152 } 153 return r; 154 } 155 156 //删除根结点 157 void Delete() 158 { 159 if(ch[root][0] == 0 || ch[root][1] == 0) 160 { 161 root = ch[root][0] + ch[root][1]; 162 pre[root] = 0; 163 return; 164 } 165 int k = Get_Min(ch[root][1]); 166 Splay(k,root); 167 Key_value = ch[root][0]; 168 root = ch[root][1]; 169 pre[ch[root][0]] = root; 170 pre[root] = 0; 171 push_up(root); 172 } 173 void bing(int x,int y) 174 { 175 int t1 = find(x),t2 = find(y); 176 if(t1 == t2)return; 177 F[t1] = t2; 178 Splay(t1,0); 179 Splay(t2,0); 180 if(size[t1] > size[t2]) 181 swap(t1,t2); 182 root = t2; 183 erase(t1); 184 } 185 int main() 186 { 187 //freopen("in.txt","r",stdin); 188 //freopen("out.txt","w",stdout); 189 int N,M; 190 int iCase = 0; 191 while(scanf("%d%d",&N,&M) == 2 ) 192 { 193 if(N == 0 && M == 0) break; 194 iCase++; 195 memset(head,-1,sizeof(head)); 196 tot = 0; 197 int v; 198 for(int i = 1;i <= N;i++) 199 { 200 scanf("%d",&v); 201 add_value(i,v); 202 } 203 for(int i = 1;i <= M;i++) 204 { 205 scanf("%d%d",&edge[i].u,&edge[i].v); 206 } 207 q_num = 0; 208 memset(used,false,sizeof(used)); 209 while(scanf("%s",&query[q_num].op) == 1) 210 { 211 if(query[q_num].op[0] == 'E')break; 212 if(query[q_num].op[0] == 'D') 213 { 214 scanf("%d",&query[q_num].x); 215 used[query[q_num].x] = true; 216 } 217 else if(query[q_num].op[0] == 'Q') 218 scanf("%d%d",&query[q_num].x,&query[q_num].y); 219 else if(query[q_num].op[0] == 'C') 220 { 221 scanf("%d%d",&query[q_num].x,&query[q_num].y); 222 add_value(query[q_num].x,query[q_num].y); 223 } 224 q_num++; 225 } 226 memset(F,-1,sizeof(F)); 227 for(int i = 1;i <= N;i++) 228 NewNode(root,0,i,to[head[i]]); 229 230 for(int i = 1;i <= M;i++) 231 if(!used[i]) 232 bing(edge[i].u,edge[i].v); 233 234 double ans = 0; 235 int cnt = 0; 236 237 for(int i = q_num-1; i>= 0 ;i--) 238 { 239 if(query[i].op[0] == 'Q') 240 { 241 Splay(query[i].x,0); 242 if(size[root] < query[i].y || query[i].y <= 0) 243 { 244 cnt++; 245 continue; 246 } 247 ans += key[Get_kth(root,size[root] - query[i].y + 1)]; 248 cnt++; 249 } 250 else if(query[i].op[0] == 'D') 251 { 252 int tmp = query[i].x; 253 bing(edge[tmp].u,edge[tmp].v); 254 } 255 else if(query[i].op[0] == 'C') 256 { 257 Splay(query[i].x,0); 258 Delete(); 259 head[query[i].x] = next[head[query[i].x]]; 260 Insert(query[i].x,to[head[query[i].x]]); 261 } 262 } 263 if(cnt == 0)cnt = 1; 264 printf("Case %d: %.6lf\n",iCase,ans/cnt); 265 } 266 return 0; 267 }