HDU 3726 Graph and Queries (离线处理+splay tree)

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 }

 

 

 

 

 

 

 

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/kuangbin/p/3292330.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞