UVALive - 5031 Graph and Queries (并查集+平衡树/线段树)
给定一个图,支持三种操作:
1.删除一条边
2.查询与x结点相连的第k大的结点
3.修改x结点的权值
解法:离线倒序操作,平衡树or线段树维护连通块中的所有结点信息,加个合并操作就行了。
感觉线段树要好写很多。
平衡树(Treap)版:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=5e5+;
struct E {
int u,v;
} e[N];
int a[N],faz[N],n,m,del[N];
int father(int x) {return ~faz[x]?faz[x]=father(faz[x]):x;} struct Treap {
static const int N=1e6+;
int rnd() {static int seed=time()%0x7fffffff; return seed=seed*48271ll%0x7fffffff;}
int ch[N][],siz[N],val[N],fa[N],tot,rd[N],rt[N];
void init() {tot=ch[][]=ch[][]=siz[]=val[]=rd[]=;}
int newnode(int x) {
int u=++tot;
ch[u][]=ch[u][]=;
siz[u]=,val[u]=x,rd[u]=rnd();
return u;
}
void pu(int u) {siz[u]=siz[ch[u][]]+siz[ch[u][]]+;}
void rot(int& u,int f) {
int v=ch[u][f];
ch[u][f]=ch[v][f^],ch[v][f^]=u;
pu(u),pu(v),u=v;
}
void ins(int& u,int x) {
if(!u) {u=newnode(x); return;}
int f=x>=val[u];
ins(ch[u][f],x);
if(rd[ch[u][f]]>rd[u])rot(u,f);
if(u)pu(u);
}
void del(int& u,int x) {
if(val[u]==x) {
if(!ch[u][])u=ch[u][];
else if(!ch[u][])u=ch[u][];
else {
int f=rd[ch[u][]]>rd[ch[u][]];
rot(u,f),del(ch[u][f^],x);
}
} else del(ch[u][x>=val[u]],x);
if(u)pu(u);
}
int kth(int u,int k) {
if(!u)return ;
int t=siz[ch[u][]]+;
if(k==t)return val[u];
return k<t?kth(ch[u][],k):kth(ch[u][],k-t);
}
void merge(int& u,int& v) {
if(!u)return;
ins(v,val[u]);
merge(ch[u][],v),merge(ch[u][],v);
}
} treap; struct Q {
int f,u,k;
} qr[N];
int nqr; void mg(int x,int y) {
int fx=father(x),fy=father(y);
if(fx==fy)return;
if(treap.siz[treap.rt[fx]]>treap.siz[treap.rt[fy]])swap(fx,fy);
treap.merge(treap.rt[fx],treap.rt[fy]);
faz[fx]=fy;
} int main() {
int kase=;
while(scanf("%d%d",&n,&m)&&n) {
treap.init();
nqr=;
memset(faz,-,sizeof faz);
for(int i=; i<=n; ++i)scanf("%d",&a[i]);
for(int i=; i<=m; ++i)scanf("%d%d",&e[i].u,&e[i].v);
char ch;
while(scanf(" %c",&ch)&&ch!='E') {
if(ch=='Q')scanf("%d%d",&qr[nqr].u,&qr[nqr].k),qr[nqr++].f=;
else if(ch=='D')scanf("%d",&qr[nqr].u),qr[nqr++].f=;
else if(ch=='C')scanf("%d%d",&qr[nqr].u,&qr[nqr].k),swap(a[qr[nqr].u],qr[nqr].k),qr[nqr++].f=;
}
for(int i=; i<=n; ++i)treap.rt[i]=treap.newnode(a[i]);
memset(del,,sizeof del);
for(int i=; i<nqr; ++i)if(qr[i].f==)del[qr[i].u]=;
for(int i=; i<=m; ++i)if(!del[i])mg(e[i].u,e[i].v);
reverse(qr,qr+nqr);
double ans=;
int cnt=;
for(int i=; i<nqr; ++i) {
if(qr[i].f==) {
int u=qr[i].u,r=treap.rt[father(u)],k=qr[i].k;
ans+=treap.kth(r,treap.siz[r]-k+),cnt++;
} else if(qr[i].f==)mg(e[qr[i].u].u,e[qr[i].u].v);
else {
int u=qr[i].u,k=qr[i].k;
int fu=father(u);
treap.del(treap.rt[fu],a[u]);
treap.ins(treap.rt[fu],k);
a[u]=k;
}
}
printf("Case %d: %f\n",++kase,ans/cnt);
}
return ;
}
线段树版:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=5e5+;
struct E {
int u,v;
} e[N];
int a[N],faz[N],n,m,del[N];
int father(int x) {return ~faz[x]?faz[x]=father(faz[x]):x;} struct Segtree {
static const int N=4e6+;
int ls[N],rs[N],siz[N],tot,rt[N];
void init() {tot=ls[]=rs[]=siz[]=;}
int newnode() {int u=++tot; ls[u]=rs[u]=siz[u]=; return u;}
void pu(int u) {siz[u]=siz[ls[u]]+siz[rs[u]];}
void add(int& u,int x,int f,int l=-,int r=) {
if(!u)u=newnode();
siz[u]+=f;
if(l==r)return;
int mid=(l+r)>>;
x<=mid?add(ls[u],x,f,l,mid):add(rs[u],x,f,mid+,r);
}
void merge(int& u,int v,int l=-,int r=) {
if(!v)return;
if(!u) {u=v; return;}
if(l==r) {siz[u]+=siz[v]; return;}
int mid=(l+r)>>;
merge(ls[u],ls[v],l,mid);
merge(rs[u],rs[v],mid+,r);
pu(u);
}
int kth(int u,int k,int l=-,int r=) {
if(l==r)return l;
int mid=(l+r)>>;
return k<=siz[ls[u]]?kth(ls[u],k,l,mid):kth(rs[u],k-siz[ls[u]],mid+,r);
}
} segtree; struct Q {
int f,u,k;
} qr[N];
int nqr; void mg(int x,int y) {
int fx=father(x),fy=father(y);
if(fx==fy)return;
segtree.merge(segtree.rt[fy],segtree.rt[fx]);
faz[fx]=fy;
} int main() {
int kase=;
while(scanf("%d%d",&n,&m)&&n) {
segtree.init();
nqr=;
memset(faz,-,sizeof faz);
for(int i=; i<=n; ++i)scanf("%d",&a[i]);
for(int i=; i<=m; ++i)scanf("%d%d",&e[i].u,&e[i].v);
char ch;
while(scanf(" %c",&ch)&&ch!='E') {
if(ch=='Q')scanf("%d%d",&qr[nqr].u,&qr[nqr].k),qr[nqr++].f=;
else if(ch=='D')scanf("%d",&qr[nqr].u),qr[nqr++].f=;
else if(ch=='C')scanf("%d%d",&qr[nqr].u,&qr[nqr].k),swap(a[qr[nqr].u],qr[nqr].k),qr[nqr++].f=;
}
for(int i=; i<=n; ++i)segtree.rt[i]=segtree.newnode(),segtree.add(segtree.rt[i],a[i],);
memset(del,,sizeof del);
for(int i=; i<nqr; ++i)if(qr[i].f==)del[qr[i].u]=;
for(int i=; i<=m; ++i)if(!del[i])mg(e[i].u,e[i].v);
reverse(qr,qr+nqr);
double ans=;
int cnt=;
for(int i=; i<nqr; ++i) {
if(qr[i].f==) {
int u=qr[i].u,r=segtree.rt[father(u)],k=qr[i].k;
if(k>&&k<=segtree.siz[r])ans+=segtree.kth(r,segtree.siz[r]-k+);
cnt++;
} else if(qr[i].f==)mg(e[qr[i].u].u,e[qr[i].u].v);
else {
int u=qr[i].u,k=qr[i].k;
int fu=father(u);
segtree.add(segtree.rt[fu],a[u],-);
segtree.add(segtree.rt[fu],k,);
a[u]=k;
}
}
printf("Case %d: %f\n",++kase,ans/cnt);
}
return ;
}
UVALive - 5031 Graph and Queries (并查集+平衡树/线段树)的更多相关文章
- 【BZOJ2054】疯狂的馒头(并查集,线段树)
[BZOJ2054]疯狂的馒头(并查集,线段树) 题面 BZOJ 然而权限题,随便找个离线题库看看题吧. 题解 线段树就是个暴力,如果数据可以构造就能卡掉,然而不能构造,要不然复杂度瓶颈成为了读入了. ...
- uvalive 5031 Graph and Queries 名次树+Treap
题意:给你个点m条边的无向图,每个节点都有一个整数权值.你的任务是执行一系列操作.操作分为3种... 思路:本题一点要逆向来做,正向每次如果删边,复杂度太高.逆向到一定顺序的时候添加一条边更容易.详见 ...
- POJ 1944 Fiber Communications (枚举 + 并查集 OR 线段树)
题意 在一个有N(1 ≤ N ≤ 1,000)个点环形图上有P(1 ≤ P ≤ 10,000)对点需要连接.连接只能连接环上相邻的点.问至少需要连接几条边. 思路 突破点在于最后的结果一定不是一个环! ...
- ACM学习历程—SNNUOJ 1110 传输网络((并查集 && 离线) || (线段树 && 时间戳))(2015陕西省大学生程序设计竞赛D题)
Description Byteland国家的网络单向传输系统可以被看成是以首都 Bytetown为中心的有向树,一开始只有Bytetown建有基站,所有其他城市的信号都是从Bytetown传输过来的 ...
- 2019牛客第八场多校 E_Explorer 可撤销并查集(栈)+线段树
目录 题意: 分析: @(2019牛客暑期多校训练营(第八场)E_Explorer) 题意: 链接 题目类似:CF366D,Gym101652T 本题给你\(n(100000)\)个点\(m(1000 ...
- UVALive 5031 Graph and Queries (Treap)
删除边的操作不容易实现,那么就先离线然后逆序来做. 逆序就变成了合并,用并存集判断连通,用Treap树来维护一个连通分量里的名次. Treap = Tree + Heap.用一个随机的优先级来平衡搜索 ...
- UVaLive 5031 Graph and Queries (Treap)
题意:初始时给出一个图,每个点有一个权值,三种操作:(1)删除某个边:(2)修改每个点的权值:(3)询问与节点x在一个连通分量中所有点的第K大的权值. 析:首先是要先离线,然后再倒着做,第一个操作就成 ...
- HDU 3974 Assign the task 并查集/图论/线段树
Assign the task Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...
- CodeForces - 505B Mr. Kitayuta's Colorful Graph 二维并查集
Mr. Kitayuta's Colorful Graph Mr. Kitayuta has just bought an undirected graph consisting of n verti ...
随机推荐
- Eclipse部署项目的时候抛异常【Multiple Contexts have a path of "/cdcpm".】
Eclipse部署项目的时候抛异常[Multiple Contexts have a path of "/cdcpm".]重新clean .删除server都不好使.查看一下tom ...
- range基础
collapse这个方法是把结束位置抛弃掉,并不是简单的设置到开始位置. 结束位置被抛弃掉以后,只要没有给它重新设置位置,它就一直都会等 于开始位置.即使你修改了开始位置,结束位置还是会在修改后的开始 ...
- Django 之models进阶操作
到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作 ...
- PAT 天梯赛 L2-021. 点赞狂魔 【水】
题目链接 https://www.patest.cn/contests/gplt/L2-021 题意 给出一个若干个人名,后面给出点赞的总数,以及每个赞的标签类型,输出前三个点赞狂魔,按标签类型不同数 ...
- Listening Carefully SP1403
Listening Carefully仔细聆听When people talk, listen completely. Most people never listen. ―Ernest Heming ...
- 12个提问频率最高的php面试题
你是否正在准备寻找一份PHP开发的工作,并且也在寻找一些关于PHP的面试题及答案?本文为大家分享了一些被提问频率最高的11个PHP面试题,以及对应的常规回答,每个公司都有自己的面试标准,面试和问题是完 ...
- win10 x64下的DNW驱动不完全安装方法【转】
本文转载自:https://blog.csdn.net/sihaiwenshu/article/details/52503550 一.起因 最新心血来潮想学ARM,JZ2440开发板买回来后就开始折腾 ...
- 为多个文件夹下的C源代码编写Makefile文件
上一篇文章写了如何为在同一个文件夹下的C源代码,本篇文章为多个文件夹下的C源代码编写Makefile文件. 建立两个文件夹,分别为abs与src.其最终目录结构如下: 1 $ ls * 2 jun.c ...
- 多校hdu5754(博弈)
©此题中在N×M的棋盘中从(1,1)走到(N,M)B先走G后走,谁先到(N,M)谁赢,走法分为4中分别是国际象棋中的国王,车,马,王后的发,在四种走法下谁能赢: 我们依次分析每一种棋子. ①王. 首先 ...
- MSER最稳定极值区域源码分析
最稳定极值区域介绍 如把灰度图看成高低起伏的地形图,其中灰度值看成海平面高度的话,MSER的作用就是在灰度图中找到符合条件的坑洼.条件为坑的最小高度,坑的大小,坑的倾斜程度,坑中如果已有小坑时大坑与小 ...