LA - 5031 - Graph and Queries

时间:2023-02-06 17:06:23

题意:一个N个点(编号从1开始),M条边的无向图(编号从1开始),有3种操作:

D X:把编号为X的边删了;

Q X K:查询编号为X的结点所在连通分量第K大的元素;

C X V:将编号为X的结点的权值修改为V。

问所有查询的结果的平均值(1 <= N <= 20000, 0 <= M <= 60000, -10^6 <= 点权 <= 10^6, 1 <= Q操作次数 <= 2 * 10^5, C操作次数 <= 2 * 10^5)。

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3032

——>>LJ《训练指南》Treap树的例题,题目中关于Q操作的话:among all vertexes currently connected with vertex X,总觉得指的是与X直接相连的结点,可实现上却应理解为X所在连通分量的所有结点。

#include <cstdio>
#include <cstring>
#include <cstdlib> using namespace std; const int maxn = 20000 + 10;
const int maxm = 60000 + 10;
const int maxc = 500000 + 10; struct Command{
char type;
int x, p;
Command(char type = '\0', int x = 0, int p = 0):type(type), x(x), p(p){}
}; struct Node{
Node *ch[2];
int r;
int v;
int s;
Node(int v):v(v){
ch[0] = ch[1] = NULL;
r = rand();
s = 1;
} bool operator < (const Node& e) const{
return r < e.r;
} int cmp(int x) const{
if(x == v) return -1;
return x < v ? 0 : 1;
} void maintain(){
s = 1;
if(ch[0] != NULL) s += ch[0]->s;
if(ch[1] != NULL) s += ch[1]->s;
}
}; int N, M, weight[maxn], from[maxm], to[maxm], fa[maxn], kase, c, query_cnt;
long long query_tot;
bool removed[maxm];
Command commands[maxc];
Node *root[maxn]; int Find(int x){
return x == fa[x] ? x : Find(fa[x]);
} void removetree(Node* &x){
if(x->ch[0] != NULL) removetree(x->ch[0]);
if(x->ch[1] != NULL) removetree(x->ch[1]);
delete x;
x = NULL;
} void rotate(Node* &o, int d){
Node* k = o->ch[d^1];
o->ch[d^1] = k->ch[d];
k->ch[d] = o;
o->maintain();
k->maintain();
o = k;
} void insert(Node* &o, int x){
if(o == NULL) o = new Node(x);
else{
int d = x < o->v ? 0 : 1;
insert(o->ch[d], x);
if(o->ch[d] > o) rotate(o, d^1);
}
o->maintain();
} void remove(Node* &o, int x){
int d = o->cmp(x);
if(d == -1){
Node* u = o;
if(o->ch[0] != NULL && o->ch[1] != NULL){
int d2 = o->ch[0] > o->ch[1] ? 1 : 0;
rotate(o, d2);
remove(o->ch[d2], x);
}
else{
if(o->ch[0] == NULL) o = o->ch[1];
else o = o->ch[0];
delete u;
}
}
else remove(o->ch[d], x);
if(o != NULL) o->maintain();
} void mergeto(Node* &src, Node* &dest){
if(src->ch[0] != NULL) mergeto(src->ch[0], dest);
if(src->ch[1] != NULL) mergeto(src->ch[1], dest);
insert(dest, src->v);
delete src;
src = NULL;
} void addEdge(int x){
int u = Find(from[x]);
int v = Find(to[x]);
if(u != v){
if(root[u]->s < root[v]->s){
fa[u] = v;
mergeto(root[u], root[v]);
}
else{
fa[v] = u;
mergeto(root[v], root[u]);
}
}
} int kth(Node* o, int k){
if(o == NULL || k <= 0 || k > o->s) return 0;
int s = (o->ch[1] == NULL ? 0 : o->ch[1]->s);
if(k == s+1) return o->v;
else if(k < s+1) return kth(o->ch[1], k);
else return kth(o->ch[0], k-s-1);
} void query(int x, int k){
query_cnt++;
query_tot += kth(root[Find(x)], k);
} void change_weight(int x, int v){
int u = Find(x);
remove(root[u], weight[x]);
insert(root[u], v);
weight[x] = v;
} void read(){
for(int i = 1; i <= N; i++) scanf("%d", &weight[i]);
for(int i = 1; i <= M; i++) scanf("%d%d", &from[i], &to[i]);
c = 0;
memset(removed, 0, sizeof(removed));
while(1){
char type;
int X, K, V;
scanf(" %c", &type);
if(type == 'E') break;
scanf("%d", &X);
if(type == 'D') removed[X] = 1;
else if(type == 'Q') scanf("%d", &K);
else{
scanf("%d", &V);
K = weight[X];
weight[X] = V;
}
commands[c++] = Command(type, X, K);
}
} void build(){
for(int i = 1; i <= N; i++){
fa[i] = i;
if(root[i] != NULL) removetree(root[i]);
root[i] = new Node(weight[i]);
}
for(int i = 1; i <= M; i++) if(!removed[i]) addEdge(i);
} void solve(){
query_tot = query_cnt = 0;
for(int i = c-1; i >= 0; i--){
if(commands[i].type == 'D') addEdge(commands[i].x);
else if(commands[i].type == 'Q') query(commands[i].x, commands[i].p);
else change_weight(commands[i].x, commands[i].p);
}
printf("Case %d: %.6lf\n", kase++, (double)query_tot / query_cnt);
} int main()
{
kase = 1;
while(scanf("%d%d", &N, &M) == 2){
if(!N && !M) return 0;
read();
build();
solve();
}
return 0;
}

LA - 5031 - Graph and Queries的更多相关文章

  1. LA 5031 Graph and Queries —— Treap名次树

    离线做法,逆序执行操作,那么原本的删除边的操作变为加入边的操作,用名次树维护每一个连通分量的名次,加边操作即是连通分量合并操作,每次将结点数小的子树向结点数大的子树合并,那么单次合并复杂度O(n1lo ...

  2. uvalive 5031 Graph and Queries 名次树&plus;Treap

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

  3. UVALive - 5031 Graph and Queries &lpar;并查集&plus;平衡树&sol;线段树&rpar;

    给定一个图,支持三种操作: 1.删除一条边 2.查询与x结点相连的第k大的结点 3.修改x结点的权值 解法:离线倒序操作,平衡树or线段树维护连通块中的所有结点信息,加个合并操作就行了. 感觉线段树要 ...

  4. UVaLive 5031 Graph and Queries &lpar;Treap&rpar;

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

  5. UVALive 5031 Graph and Queries (Treap)

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

  6. &lbrack;la P5031&amp&semi;hdu P3726&rsqb; Graph and Queries

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

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

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

  8. HDU 3726 Graph and Queries (离线处理&plus;splay tree)

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

  9. HDU 3726 Graph and Queries treap树

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

随机推荐

  1. IE下a标签后面的span元素向右浮动后错位

    错误原因span放在了a标签之后 正确写法是放在之前 如下: <li><span>2016-07-29</span><a href="#" ...

  2. &lbrack;RxJS&rsqb; Reactive Programming - Using cached network data with RxJS -- withLatestFrom&lpar;&rpar;

    So now we want to replace one user when we click the 'x' button. To do that, we want: 1. Get the cac ...

  3. 多项目中SVN权限管理精辟解析

    本节和大家讨论一下多项目SVN权限管理,主要包括建立版本库,修改版本库配置文件,配置允许访问的用户,设置用户访问权限.下面我们就来看一下SVN权限管理.svn权限管理svn的权限管理涉及到一下文件:p ...

  4. 201521123076 《Java程序设计》第8周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 2. 书面作业 1.List中指定元素的删除(题目4-1) 1.1 实 ...

  5. C&num; TreeView设置SelectedNode设置无效的问题

    在设置Treeview.SelectedNode = newTreeNode(找到的TreeNode)时,界面上没呈现选择状态. 此时可能是treeview没有获取焦点,但是即使没有焦点,也可以让选中 ...

  6. 谈谈MySQL的事务隔离级别

    这篇文章能够阐述清楚跟数据库相关的四个概念:事务.数据库读现象.隔离级别.锁机制 一.事务 先来看下百度百科对数据库事务的定义: 作为单个逻辑单元执行一系列操作,要么完全执行,要么完全不执行.事务处理 ...

  7. wpf treeview 数据绑定 递归绑定节点

    1.先上效果 将所有节点加入ComboBox数据源,在ComboBox中选择时下方Treeview显示该节点下的子节点. 1.xaml文件,将以下代码加入界面合适位置 <StackPanel&g ...

  8. Java学习笔记32(集合框架六:Map接口)

    Map接口与Collection不同: Collection中的集合元素是孤立的,可理解为单身,是一个一个存进去的,称为单列集合 Map中的集合元素是成对存在的,可理解为夫妻,是一对一对存进去的,称为 ...

  9. GridControl 获取某分组的第一个孩子

    int iGroupRowHandle = this.gridControlView.FocusedRowHandle; ) { int iChildCount = this.gridControl. ...

  10. P2059 &lbrack;JLOI2013&rsqb;卡牌游戏

    题目描述 N个人坐成一圈玩游戏.一开始我们把所有玩家按顺时针从1到N编号.首先第一回合是玩家1作为庄家.每个回合庄家都会随机(即按相等的概率)从卡牌堆里选择一张卡片,假设卡片上的数字为X,则庄家首先把 ...