Hdu 3726 Graph and Queries(删边,查询第k大,修改点值)
2016-08-25 14:20
393 查看
传送门:[(Hdu]http://acm.split.hdu.edu.cn/showproblem.php?pid=3726](Hdu 3726 Graph and Queries)
题意:给你n个点,m条边,有下面三种操作
1:D X :删掉第X条边。
2:Q X K :查询和X相连的点中第K大的点的值
3:C X V :将点X的权值修改为V
思路:逆向处理,利用并查集+Splay
按值建立Splay,修改点值,先找到这个点,让这个点作为根,删除根
删除边,判断两个点的并查集是否相同,暴力合并(每个点最多被合并logn次),所以合并时间复杂度为logn^2
题意:给你n个点,m条边,有下面三种操作
1:D X :删掉第X条边。
2:Q X K :查询和X相连的点中第K大的点的值
3:C X V :将点X的权值修改为V
思路:逆向处理,利用并查集+Splay
按值建立Splay,修改点值,先找到这个点,让这个点作为根,删除根
删除边,判断两个点的并查集是否相同,暴力合并(每个点最多被合并logn次),所以合并时间复杂度为logn^2
#include<bits/stdc++.h> using namespace std; const int INF=0x3f3f3f3f; const int N=6e4+10; const int M=6e4+10; struct query{ int op,x,k; }Q[M*10]; struct Edge{ int from,to; }E[M]; vector<int>G ,Num ; int s ,tot1,tot2,size ,val ,fa ,f ,root ,n,Siz ,flag ,cnt ,ch [2]; int case1=1; void Newnode(int &now,int father,int k){ if(tot2) now=s[tot2--]; else now=++tot1; val[now]=k,fa[now]=father,size[now]=1,cnt[now]=1; ch[now][0]=ch[now][1]=0; } void erase(int x){ if(!x) return ; s[++tot2]=x; erase(ch[x][0]),erase(ch[x][1]); } void pushup(int x){ size[x]=size[ ch[x][0] ]+size[ ch[x][1] ]+cnt[x]; } //旋转,kind为1为右旋,kind为0为左旋 void Rotate(int x,int kind){ int y=fa[x]; ch[y][!kind]=ch[x][kind]; fa[ch[x][kind]]=y; //如果父节点不是根结点,则要和父节点的父节点连接起来 if(fa[y]) ch[ fa[y] ][ch[fa[y]][1]==y]=x; fa[x]=fa[y]; ch[x][kind]=y; fa[y]=x; pushup(y); } //Splay调整,将根为now的子树调整为goal void Splay(int now,int goal,int Belong){ while(fa[now]!=goal){ if(fa[ fa[now] ]==goal) Rotate(now,ch[ fa[now] ][0]==now); else{ int pre=fa[now],kind=ch[ fa[pre] ][0]==pre; //左儿子为1,右儿子为0 if(ch[pre][kind]==now){ //两个方向不同 Rotate(now,!kind); Rotate(now,kind); } else{ //两个方向相同 Rotate(pre,kind); Rotate(now,kind); } } } if(goal==0) root[Belong]=now; pushup(now); } int get_kth(int x,int k){ int num1=size[ch[x][0]]; int num2=size[ch[x][0]]+cnt[x]; if(num1<k&&num2>=k) return x; if(num1>=k) return get_kth(ch[x][0],k); return get_kth(ch[x][1],k-num2); } int find(int x){ if(x==f[x]) return f[x]; f[x]=find(f[x]); return f[x]; } char str[3]; void init(){ tot1=tot2=0; for(int i=1;i<=n;i++){ Newnode(root[i],0,-INF); Newnode(ch[root[i]][1],root[i],INF); Newnode(ch[ch[root[i]][1]][0],ch[root[i]][1],Num[i].back()); pushup(ch[root[i]][1]),pushup(root[i]); } } void Insert(int k,int Belong){ int now=root[Belong]; while(ch[now][val[now]<k]){ if(val[now]==k){ Splay(now,0,Belong),cnt[root[Belong]]++; pushup(root[Belong]); return ; } now=ch[now][val[now]<k]; } Newnode(ch[now][k>val[now]],now,k); //将新插入的结点更新至根结点 Splay(ch[now][k>val[now]],0,Belong); return ; } int getmax(int x){ while(ch[x][1]) x=ch[x][1]; return x; } void remove(int Belong){ int m=getmax(ch[root[Belong]][0]); Splay(m,root[Belong],Belong); ch[m][1]=ch[root[Belong]][1]; fa[ch[root[Belong]][1]]=m; root[Belong]=m; fa[root[Belong]]=0; pushup(root[Belong]); } void Delete(int k,int Belong){ int now=root[Belong]; while(ch[now][val[now]<k]){ if(val[now]==k){ Splay(now,0,Belong); if(cnt[root[Belong]]>1) cnt[root[Belong]]--; else{ s[++tot2]=root[Belong]; remove(Belong); } pushup(root[Belong]); return ; } now=ch[now][val[now]<k]; } if(val[now]==k){ Splay(now,0,Belong); if(cnt[root[Belong]]>1) cnt[root[Belong]]--; else{ s[++tot2]=root[Belong]; remove(Belong); } pushup(root[Belong]); return ; } } void Union(int x,int y){ erase(root[y]),root[y]=0,fa[root[y]]=0; for(int i=0;i<G[y].size();i++){ G[x].push_back(G[y][i]); Insert(Num[ G[y][i] ].back(),x); } G[y].clear(); } void merge(int from,int to){ int x=find(from),y=find(to); if(x==y) return ; if(Siz[x]>Siz[y]) Union(x,y),f[y]=x,Siz[x]+=Siz[y]; else Union(y,x),f[x]=y,Siz[y]+=Siz[x]; } void travel(int x){ if(x==0) return ; travel(ch[x][0]); printf("%d ",val[x]); travel(ch[x][1]); } void change(int x,int k){ int xx=find(x); Num[x].pop_back(); Delete(k,xx); Insert(Num[x].back(),xx); //更新为这个 } int main(){ int m,x; while(scanf("%d%d",&n,&m)!=EOF){ if(n==0&&m==0) break; memset(flag,0,sizeof(flag)); for(int i=1;i<=n;i++) f[i]=i,Siz[i]=1,G[i].clear(),Num[i].clear(); for(int i=1;i<=n;i++) scanf("%d",&x),G[i].push_back(i),Num[i].push_back(x); for(int i=1;i<=m;i++) scanf("%d%d",&E[i].from,&E[i].to); int cnt=0; for(int i=1;;i++){ scanf("%s",str); if(str[0]=='E'){ cnt=i-1; break; } if(str[0]=='D') Q[i].op=1,scanf("%d",&Q[i].x),flag[Q[i].x]=1; else if(str[0]=='Q') Q[i].op=2,scanf("%d%d",&Q[i].x,&Q[i].k); else Q[i].op=3,scanf("%d%d",&Q[i].x,&Q[i].k),Num[Q[i].x].push_back(Q[i].k); } init(); for(int i=1;i<=m;i++) if(flag[i]==0) merge(E[i].from,E[i].to); double ans=0; int Count=0; for(int i=cnt;i>=1;i--){ if(Q[i].op==1) merge(E[Q[i].x].from,E[Q[i].x].to); else if(Q[i].op==2){ Count++; int x=find(Q[i].x); if(size[root[x]]-Q[i].k>=2&&Q[i].k>=1) ans+=val[get_kth(root[x],size[root[x]]-Q[i].k)]; } else change(Q[i].x,Q[i].k); } printf("Case %d: %.6f\n",case1++,ans/Count); } return 0; }
相关文章推荐
- hdu 3726 Graph and Queries(splay查询第k大,启发式合并,删除操作)
- 【HDU】3726 Graph and Queries
- hdu 3726 Graph and Queries
- HDU 3726 Graph and Queries splay 离线 模拟
- HDU 3726 Graph and Queries
- hdu 3726 Graph and Queries , 天津 2010, LA 5031,并查集,Treap,离线处理
- HDU 3726 Graph and Queries 平衡树+前向星+并查集+离线操作+逆向思维 数据结构大综合题
- hdu 3726 Graph and Queries 名次树
- HDU 3726 Graph and Queries(平衡二叉树)(2010 Asia Tianjin Regional Contest)
- hdu 3726 Graph and Queries 10天津赛区 离线算法+treap维护名次树
- HDU 3726 Graph and Queries (Treap)
- Hdu 3726 Graph and Queries(并查集+平衡树+启发式合并)
- HDU 3726 Graph and Queries 离线处理 treap + 并查集
- hdu 3726 Graph and Queries 名次树
- hdu 3726 Graph and Queries (Treap应用,名次树)
- HDU 3726 Graph and Queries Treap
- HDU 3726 Graph and Queries (离线处理+splay tree)
- HDU 3726 Graph and Queries(treap)
- 【treap tree】 HDOJ 3726 && LA 5031 && UVA 1479 Graph and Queries
- 查询和修改(Queries and Mutations)