UVA 1479 Graph and Queries(Treap:名次树+并查集)
来源:互联网 发布:发货找物流软件 编辑:程序博客网 时间:2024/05/22 14:55
UVA 1479 Graph and Queries(Treap:名次树+并查集)
题意:
给你一个无向图,每个顶点具有权值,现在对图进行操作,你需要输出最后查询操作的平均值.有查询,删除边,改变点的权值三种操作.
分析:
刘汝佳训练指南P234例题.
首先读入所有的操作,点以及边.由于只需要我们输出最后的一个平均结果,所以我们把这些操作逆序处理,使得从图中删除边,变成往图中添加边并合并连通分量.
首先读入所有命令,对于删除边i的命令,我们就令边i无效即可.(我们依然保存所有边的信息).对于修改x点权值为v的命令,我们就直接改变x的权值y为v,并且保存一条该x权值为y的命令.(即逆转)对于查询命令,我们不管直接保存下来.
现在我们对初始的每个节点建立一个单独的Treap节点,并且一一读入所有有效的边(即经过所有删除操作还剩下的边)并且合并两个边所属的连通分量(同时合并两个连通分量的Treap树,将小树的节点一一合入大树).
接下来我们就逆序处理所有的命令了,对于D命令就是添加边合并连通分量并且合并Treap树.对于Q命令就是查询当前节点所属连通分量Treap树的第K大值V.对于C命令就是先删除特定节点在插入特定节点.
总之对于一个节点x,任何时候它所属的Treap数根编号都是它的连通分量的根的编号.
代码少写了merge中b的应用符号,WA了半天.
AC代码:
#include<cstdio>#include<cstdlib>#include<cstring>using namespace std;struct Node{ Node *ch[2]; int r,v,s;//s表示节点数 Node(int v):v(v) { ch[0]=ch[1]=NULL; r=rand(); s=1; } bool operator<(const Node &b)const { return r<b.r; } int cmp(int x) { 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; }};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)//o子树中事先不存在x{ if(o==NULL) { o=new Node(x); } else { int d=(x < o->v)? 0:1;//允许相同的v值在Treap中,所以注意这里的写法,不能用cmp insert(o->ch[d],x); if(o->ch[d]>o) rotate(o,d^1); } o->maintain();}void remove(Node* &o,int x)//o子树中实现必须存在x{ int d=o->cmp(x); if(d==-1) { Node *u=o; if(o->ch[0] && o->ch[1]) { 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) o->maintain();//之前o存在,但是删除节点后o可能就是空NULL了,所以需要先判断o是否为空}const int maxn=20000+100;const int maxm=60000+100;int weight[maxn];struct edge{ int u,v;}edges[maxm];struct command{ int type;//0,1,2,对于D,Q,C int x,p;}coms[600000+1000];int cnt;//命令条数bool removed[maxm];int F[maxn];int findset(int i){ if(F[i]==-1) return i; return F[i]=findset(F[i]);}Node *nodes[maxn];int kth(Node* o,int k)//注意这是求第k大,不是第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) return kth(o->ch[1],k); else return kth(o->ch[0],k-s-1);}void merge(Node *&a,Node *&b)//少写了b的应用符号,WA了半天{ if(a->ch[0]) merge(a->ch[0],b); if(a->ch[1]) merge(a->ch[1],b); insert(b,a->v); delete a; a=NULL;}void removetree(Node *&a){ if(a->ch[0]) removetree(a->ch[0]); if(a->ch[1]) removetree(a->ch[1]); delete a; a=NULL;}void add_edge(int e){ int x=findset(edges[e].u), y=findset(edges[e].v); if(x!=y) { if(nodes[x]->s < nodes[y]->s) {F[x]=y; merge(nodes[x],nodes[y]);} else {F[y]=x; merge(nodes[y],nodes[x]);} }}int query_cnt;long long query_tot;void query(int x,int k){ int fx=findset(x); query_tot+= kth(nodes[fx],k); query_cnt++;}void change_weight(int x,int v){ int u=findset(x); remove(nodes[u],weight[x]); insert(nodes[u],v); weight[x]=v;}int main(){ int n,m,kase=0; while(scanf("%d%d",&n,&m)==2&&n) { if(n==0&&m==0) break; memset(removed,0,sizeof(removed)); for(int i=1;i<=n;i++) scanf("%d",&weight[i]); for(int i=1;i<=m;i++) scanf("%d%d",&edges[i].u,&edges[i].v); char str[100]; int x,p; cnt=0; while(scanf("%s",str)==1) { if(str[0]=='E') break; scanf("%d",&x); if(str[0]=='D') { coms[cnt++]=(command){0,x,0}; removed[x]=true; } else if(str[0]=='Q') { scanf("%d",&p); coms[cnt++]=(command){1,x,p}; } else if(str[0]=='C') { int v; scanf("%d",&v); p=weight[x]; weight[x]=v; coms[cnt++]=(command){2,x,p}; } } for(int i=1;i<=n;i++) { F[i]=-1; if(nodes[i]) removetree(nodes[i]); nodes[i]=new Node(weight[i]); } for(int i=1;i<=m;i++)if(!removed[i]) add_edge(i); query_tot=query_cnt=0; for(int i=cnt-1;i>=0;i--) { if(coms[i].type==0) add_edge(coms[i].x); else if(coms[i].type==1) query(coms[i].x,coms[i].p); else if(coms[i].type==2) change_weight(coms[i].x,coms[i].p); } //printf("tot=%I64d, cnt=%d\n",query_tot,query_cnt); printf("Case %d: %.6lf\n", ++kase, query_tot / (double)query_cnt); } return 0;}
0 0
- UVA 1479 Graph and Queries(Treap:名次树+并查集)
- LA 5031 Graph and Queries (【名次树(treap)】+【并查集】+【离线算法】)
- uva1479 - Graph and Queries Treap名次树
- UVA 1479 Graph and Queries(Treap树)
- uva live 5031 Graph and Queries(Treap x 并查集)
- LA 5031 Graph and Queries (Treap + 并查集)
- HDU 3276 Graph and Queries [离线+并查集+treap]
- UvaLive 5031 Graph and Queries(Treap+并查集)
- UVA 1479 - Graph and Queries(Treap)
- 【UVALive】5031 Graph and Queries treap实现名次树
- hdu 3726 Graph and Queries (Treap应用,名次树)
- hdu 3726 Graph and Queries , 天津 2010, LA 5031,并查集,Treap,离线处理
- HDU 3726 Graph and Queries 离线处理 treap + 并查集
- Uva 5031 Graph and Queries(Treap)
- LA 5031 Graph and Queries (离线处理 + Treap树维护名次)
- hdu 3726 Graph and Queries 名次树
- HDU 3726 Graph and Queries treap树
- uva 1479 - Graph and Queries(伸展树)
- 手机地图功能设计--本地生活入口之一
- iOS网络编程(一)NSURLConnection
- 上传下载
- 测量listview时自定义listview
- java Antlr学习 错误列表 ErrorList
- UVA 1479 Graph and Queries(Treap:名次树+并查集)
- hdu 1285 确定比赛名次(拓扑排序)
- 删除dll文件
- 工作总结11 压缩文件里面的中文文件名读取乱码问题解决方案
- Repo Manifest 格式(XML文件)
- 【OpenCV】cvColor在OpenCV中的应用
- 翻译- O'Reilly ZooKeeper-第一章 入门
- 动态规划解最大公共子串
- AD10的DRC检查