题目链接: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次询问的平均值

大白上的例题, 离线处理,把所有操作 反过来处理,,这样删边变成了 加边,,瞬间好处理多了。。细节也有很多。

 #include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const double eps = 1e-;
const int maxn = 2e4+;
int n, m, val[maxn];
int pa[maxn];
void init()
{
for (int i = ; i <= n; i++)
{
pa[i] = i;
}
}
int find(int x)
{
return pa[x] = (pa[x] == x ? x : find(pa[x]));
}
struct Node
{
Node* ch[];
int key, r, siz;
Node (int x)
{
key = x;
siz = ;
ch[] = ch[] = NULL;
r = rand();
}
bool operator < (const Node &rhs)const
{
return r < rhs.r;
}
int cmp(int x)
{
if (x == key)
return -;
return x < key ? : ;
}
void maintain()
{
siz = ;
if (ch[] != NULL)
siz += ch[] -> siz;
if (ch[] != NULL)
siz += ch[] -> siz;
}
};
void rotate(Node* &root, int d)
{
Node* tmp = root -> ch[d^];
root -> ch[d^] = tmp -> ch[d];
tmp -> ch[d] = root;
root -> maintain();
tmp -> maintain();
root = tmp;
}
void insert(Node* &root, int x)
{
if (root == NULL)
root = new Node (x);
else
{
int d = x < root -> key ? : ;
insert (root ->ch[d], x);
if (root -> ch[d] -> r > root -> r)
rotate(root, d^); }
root -> maintain();
}
void dele(Node* &root, int x)
{
int d = root -> cmp(x);
if (d == -)
{
Node* tmp = root;
if (root -> ch[] != NULL && root -> ch[] != NULL)
{
int d1 = (root -> ch[] -> r > root -> ch[] -> r ? : );
rotate(root, d1^);
dele(root -> ch[d1^], x);
}
else
{
if (root -> ch[] == NULL)
root = root -> ch[];
else
root = root -> ch[];
delete tmp;
}
}
else
dele(root->ch[d], x);
if (root != NULL)
root -> maintain();
}
int Get_kth(Node* root, int k)
{
if (root == NULL || k <= || root -> siz < k)
return ;
int s = root -> ch[] == NULL ? : root -> ch[] -> siz;
if (s + == k)
return root -> key;
if (s + > k)
return Get_kth(root -> ch[], k);
else
return Get_kth(root -> ch[], k-s-); }
Node* root[maxn];
void merge_tree(Node* &src, Node* &fa)
{
if (src -> ch[] != NULL)
merge_tree(src -> ch[], fa);
if (src -> ch[] != NULL)
merge_tree(src -> ch[], fa);
insert(fa, src -> key);
delete src;
src = NULL;
}
void remove_tree(Node* &root)
{
if (root -> ch[] != NULL)
remove_tree(root -> ch[]);
if (root -> ch[] != NULL)
remove_tree(root -> ch[]);
delete root;
root = NULL;
}
struct
{
int x, y;
bool is_del;
} e[ * maxn];
struct
{
int type, x, p;
} Q[maxn*];
void add_edge(int idx)
{
int fx = find(e[idx].x);
int fy = find(e[idx].y);
if (fx != fy)
{
if (root[fx] -> siz > root[fy] -> siz)
{
pa[fy] = fx;
merge_tree(root[fy], root[fx]);
}
else
{
pa[fx] = fy;
merge_tree(root[fx], root[fy]); }
} }
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int cas = ;
while (~ scanf ("%d%d",&n, &m))
{
if (n == && m == )
break;
for (int i = ; i < n; i++)
{
scanf ("%d", val + + i);
}
for (int i = ; i <= m; i++)
{
scanf ("%d%d", &e[i].x, &e[i].y);
e[i].is_del = false;
}
char op[];
int tot = ;
while (scanf ("%s",op) && op[] != 'E')
{
if (op[] == 'D')
{
scanf ("%d", &Q[tot].x);
Q[tot++].type = ;
e[Q[tot-].x].is_del = true;
}
if (op[] == 'Q')
{
scanf ("%d%d", &Q[tot].x, &Q[tot].p);
Q[tot++].type = ;
}
if (op[] == 'C')
{
int v;
scanf ("%d%d", &Q[tot].x, &v);
Q[tot].p = val[Q[tot].x];
val[Q[tot].x] = v;
Q[tot++].type = ;
}
}
init();
for (int i = ; i < n; i++)
{
if (root[i+] != NULL)
remove_tree(root[i+]);
root[i+] = new Node (val[i+]);
}
for (int i = ; i < m; i++)
{
if (e[i+].is_del == false)
add_edge(i+);
}
ll ans1 = , ans2 = ;
for (int i = tot - ; i >= ; i--)
{
if (Q[i].type == )
{
add_edge(Q[i].x);
}
if (Q[i].type == )
{
ans1 += Get_kth(root[find(Q[i].x)], Q[i].p);
ans2 ++;
}
if (Q[i].type == )
{
int father = find(Q[i].x);
dele (root[father], val[Q[i].x]);
insert (root[father], Q[i].p);
val[Q[i].x] = Q[i].p;
}
}
printf("Case %d: %.6f\n", cas++, 1.0*ans1 / ans2);
}
return ;
}

HDU3726---Graph and Queries 离线处理+Treap的更多相关文章

  1. [HDU3726]Graph and Queries

    Problem 给你一张图,点的权值,边和几个操作: D x: 删除第x条边 Q x y: 询问包含x的联通块中权值第y大的权值 C x y: 将x这个点的权值改为y Solution 一看就要离线处 ...

  2. uvalive 5031 Graph and Queries 名次树+Treap

    题意:给你个点m条边的无向图,每个节点都有一个整数权值.你的任务是执行一系列操作.操作分为3种... 思路:本题一点要逆向来做,正向每次如果删边,复杂度太高.逆向到一定顺序的时候添加一条边更容易.详见 ...

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

    Graph and Queries Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  4. HDU 3726 Graph and Queries treap树

    题目来源:HDU 3726 Graph and Queries 题意:见白书 思路:刚学treap 參考白皮书 #include <cstdio> #include <cstring ...

  5. HDU 3726 Graph and Queries 平衡树+前向星+并查集+离线操作+逆向思维 数据结构大综合题

    Graph and Queries Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  6. [la P5031&hdu P3726] Graph and Queries

    [la P5031&hdu P3726] Graph and Queries Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: ...

  7. UVaLive 5031 Graph and Queries (Treap)

    题意:初始时给出一个图,每个点有一个权值,三种操作:(1)删除某个边:(2)修改每个点的权值:(3)询问与节点x在一个连通分量中所有点的第K大的权值. 析:首先是要先离线,然后再倒着做,第一个操作就成 ...

  8. UVALive 5031 Graph and Queries (Treap)

    删除边的操作不容易实现,那么就先离线然后逆序来做. 逆序就变成了合并,用并存集判断连通,用Treap树来维护一个连通分量里的名次. Treap = Tree + Heap.用一个随机的优先级来平衡搜索 ...

  9. UVALive5031 Graph and Queries(Treap)

    反向操作,先求出最终状态,再反向操作. 然后就是Treap 的合并,求第K大值. #include<cstdio> #include<iostream> #include< ...

随机推荐

  1. Java 数量为5的线程池同时运行5个窗口买票,每隔一秒钟卖一张票

    /** * 1.创建线程数量为5的线程池 * 2.同时运行5个买票窗口 * 3.总票数为100,每隔一秒钟卖一张票 * @author Administrator * */ public class ...

  2. gzip优化网络传输量提高传输效率[转]

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO;us ...

  3. HDFS集群balance(3)-- 架构细节

    转载请注明博客地址:http://blog.csdn.net/suileisl HDFS集群balance,对应版本balance design 6 如需word版本,请QQ522173163联系索要 ...

  4. PYCURL ERROR 22 - "The requested URL returned error: 403 Forbidden"

    RHEL6.5创建本地Yum源后,发现不可用,报错如下: [root@namenode1 html]# yum install gcc Loaded plugins: product-id, refr ...

  5. JPush 极光推送 消息推送 实例

    简介 官网:https://www.jpush.cn/ 极光推送(JPush)是一个端到端的推送服务,使得服务器端消息能够及时地推送到终端用户手机上,让开发者积极地保持与用户的连接,从而提高用户活跃度 ...

  6. GridView下DropDownList 的选择方法onselectedindexchanged 实现方法

    在GridView下面绑定好了下拉框,我们常常会遇到一个问题, 选择方法怎么实现呢,用js总是难的去算是在GridView的第几行第几个元素,因为服务器的id和客户端的id经常变化让js根本无从找起, ...

  7. HTML5触摸屏touch事件使用介绍1

    市面上手机种类繁多,在触屏手机上运行的网页跟传统PC网页相比还是有很大差别的.由于设备的不同浏览器的事件的设计也不同.传统PC站的 click 和 onmouseover 等事件在一般触屏的手机上也可 ...

  8. pt-query-digest 安装及使用

    打个草稿 介绍:pt-query-digest 可用于mysql的慢查询的日志分析,分析统计出每种慢查询的基本信息,如响应时间.最大执行时间.最小执行时间.执行时间的中位数等.(当然不只是这个功能) ...

  9. C++ 性能剖析 (二):值语义 (value semantics)

    Value Semantics (值语义) 是C++的一个有趣的话题. 什么是值语义? 简单的说,所有的原始变量(primitive variables)都具有value semantics. 也可以 ...

  10. epoll 中EPOLLIN 和 EPOLLOUT

    epoll主要是事件回调运行的,我们使用socket的时候主要使用两个事件 EPOLLOUT事件:EPOLLOUT事件只有在连接时触发一次,表示可写,其他时候想要触发,那你要先准备好下面条件:1.某次 ...