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 ...
随机推荐
- vs2015 安卓相关配置
vs2015的安卓相关配置百度不到,园子里也没人写.还是我没搜索到? 看来只能靠自己的英(pin)语(yin)能力一点点解决了 安装2015这个过程没啥可说的.都安装就OK了. 重要的就是选择安卓程序 ...
- Android:日常学习笔记(8)———探究UI开发(5)
Android:日常学习笔记(8)———探究UI开发(5) ListView控件的使用 ListView概述 A view that shows items in a vertically scrol ...
- springboot-整合freemarker
freemarker是一个页面模板引擎.用springboot整合freemarker的方式如以下步骤: 1.在创建springboot的项目的时候,选择freemarker的组件,或者自己手动在ma ...
- linux基础四----samba&&nginx
一 samba 1环境配置: a.确保linux下防火墙关闭比或开放共享目录权限 iPtables -F b.确保setlinux关闭:setenforce 0 c.配置iP 2安装软件包:yum i ...
- P4317 花神的数论题
题目 洛谷 数学方法学不会%>_<% 做法 爆搜二进制下存在\(i\)位\(1\)的情况,然后快速幂乘起来 My complete code #include<bits/stdc++ ...
- css transform常用变化解析
本文旨在对常用变化做最直观的简析 translate 移动 translateX() X轴正方向移动(单位可为px,也可为%,为%时以自身为参照物) translateY() Y轴反方向移动 tran ...
- Windows Server 2008 IIS的备份和还原
Windows Server 2008 IIS的备份和还原 当我们服务器系统有大量的站点和虚拟目录的时候,因为种种原因需要重做系统,那么重装系统后这些站点我们是否只能一个一个的添加,如果有成百上千个站 ...
- 虚拟机开启Linux时出现“我以复制虚拟机”、“我已移动虚拟机”
当出现标题的情况时,并且网络出现状况时,可以尝试一下解决办法 首先用ifconfig -a命令调出现在的网卡驱动的名称和HWaddr地址,然后再编辑/etc/sysconfig/networking/ ...
- [Codechef November Challenge 2012] Arithmetic Progressions
题意:给定一个序列,求多少个三元组满足ai+ak=2*aj(i<j<k). 题解:原来叉姐的讲义上有啊..完全忘掉了.. 首先这个式子很明显是一个卷积.我们有了FFT的思路.但是肯定不能每 ...
- nodejs下载安装教程(XP版)
Node.js 下载安装教程(XP版) 参考自:https://www.cnblogs.com/zhouyu2017/p/6485265.html(win10版) 一.安装环境 Windows Xp( ...