zoukankan      html  css  js  c++  java
  • 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 [-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.

     
    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
     
    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_2HDU3726.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
    ",iCase,ans/cnt);
    265     }
    266     return 0;
    267 }
  • 相关阅读:
    界面控件DevExpress ASP.NET Controls v21.2 甘特图性能增强
    New!DevExpress ASP.NET v21.2最新版本系统环境配置要求
    界面控件DevExpress WinForm MVVM命令讲解(一)
    界面控件DevExpress WPF入门级教程 触摸滚动条
    DevExtreme初级入门教程(React篇) 应用程序模板(Part 1)
    WinForm应用界面美化攻略 MVVM 高级绑定功能
    Telerik UI组件官宣支持.NET 6 和 VS 2022,让现代UI变得更简单
    界面控件Telerik UI for WinForm初级教程 版本升级
    界面控件DevExpress WPF入门指南 表达式 & 表达式编辑器
    DevExtreme初级入门教程(React篇) 应用程序模板(Part 2)
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3292330.html
Copyright © 2011-2022 走看看