Hdu 3726 Graph and Queries(并查集+平衡树+启发式合并)
2015-05-19 21:25
507 查看
题目链接
Total Submission(s): 2649 Accepted Submission(s): 600
[align=left]Problem Description[/align]
You are given an undirected graph with N vertexes and M edges. Every vertex in this graph has an integer value assigned to it at the beginning. You're also given a sequence of operations and you need to process them as requested.
Here's a list of the possible operations that you might encounter:
1) Deletes an edge from the graph.
The format is [D X], where X is an integer from 1 to M, indicating the ID of the edge that you should delete. It is guaranteed that no edge will be deleted more than once.
2) Queries the weight of the vertex with K-th maximum value among all vertexes currently connected with vertex X (including X itself).
The format is [Q X K], where X is an integer from 1 to N, indicating the id of the vertex, and you may assume that K will always fit into a 32-bit signed integer. In case K is illegal, the value for that query will be considered as undefined, and you should
return 0 as the answer to that query.
3) Changes the weight of a vertex.
The format is [C X V], where X is an integer from 1 to N, and V is an integer within the range [-106, 106].
The operations end with one single character, E, which indicates that the current case has ended.
For simplicity, you only need to output one real number - the average answer of all queries.
[align=left]Input[/align]
There are multiple test cases in the input file. Each case starts with two integers N and M (1 <= N <= 2 * 104, 0 <= M <= 6 * 104), the number of vertexes in the graph. The next N lines describes the initial
weight of each vertex (-106 <= weight[i] <= 106). The next part of each test case describes the edges in the graph at the beginning. Vertexes are numbered from 1 to N. The last part of each test case describes the operations to be performed on the
graph. It is guaranteed that the number of query operations [Q X K] in each case will be in the range [1, 2 * 105], and there will be no more than 2 * 105 operations that change the values of the vertexes [C X V].
There will be a blank line between two successive cases. A case with N = 0, M = 0 indicates the end of the input file and this case should not be processed by your program.
[align=left]Output[/align]
For each test case, output one real number – the average answer of all queries, in the format as indicated in the sample output. Please note that the result is rounded to six decimal places.
[align=left]Sample Input[/align]
[align=left]Sample Output[/align]
题意:n个结点,m条边的无向图,每个节点有一个整数权值。
3种操作:
D X,删除id为X的边。输入保证每条边至多被删除一次。
Q X k , 计算与结点X联通的结点中(包括X),第K大的权值。如果不存在,输出0。
C X V,把结点X的权值改为V
输出所有询问的平均值。
题解:离线操作,我们把操作倒过来,把删边操作转换为加边。由于要询问第K大,所以我们用平衡树维护一个联通块中的点。当我们要合并两个联通块时,将结点数小的平衡树中的点加入另一个平衡树,删除结点数小的平衡树,这样的合并称为启发式合并。我们来分析一下复杂度,由于1个点合并以后,它所在的树的范围至少增大一倍。所以这个点最多合并logn次,每次合并的复杂度为logn,所以合并的总复杂度为O(n*logn*logn)。单次询问和修改的复杂度为logn。
代码如下:
Graph and Queries
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2649 Accepted Submission(s): 600
[align=left]Problem Description[/align]
You are given an undirected graph with N vertexes and M edges. Every vertex in this graph has an integer value assigned to it at the beginning. You're also given a sequence of operations and you need to process them as requested.
Here's a list of the possible operations that you might encounter:
1) Deletes an edge from the graph.
The format is [D X], where X is an integer from 1 to M, indicating the ID of the edge that you should delete. It is guaranteed that no edge will be deleted more than once.
2) Queries the weight of the vertex with K-th maximum value among all vertexes currently connected with vertex X (including X itself).
The format is [Q X K], where X is an integer from 1 to N, indicating the id of the vertex, and you may assume that K will always fit into a 32-bit signed integer. In case K is illegal, the value for that query will be considered as undefined, and you should
return 0 as the answer to that query.
3) Changes the weight of a vertex.
The format is [C X V], where X is an integer from 1 to N, and V is an integer within the range [-106, 106].
The operations end with one single character, E, which indicates that the current case has ended.
For simplicity, you only need to output one real number - the average answer of all queries.
[align=left]Input[/align]
There are multiple test cases in the input file. Each case starts with two integers N and M (1 <= N <= 2 * 104, 0 <= M <= 6 * 104), the number of vertexes in the graph. The next N lines describes the initial
weight of each vertex (-106 <= weight[i] <= 106). The next part of each test case describes the edges in the graph at the beginning. Vertexes are numbered from 1 to N. The last part of each test case describes the operations to be performed on the
graph. It is guaranteed that the number of query operations [Q X K] in each case will be in the range [1, 2 * 105], and there will be no more than 2 * 105 operations that change the values of the vertexes [C X V].
There will be a blank line between two successive cases. A case with N = 0, M = 0 indicates the end of the input file and this case should not be processed by your program.
[align=left]Output[/align]
For each test case, output one real number – the average answer of all queries, in the format as indicated in the sample output. Please note that the result is rounded to six decimal places.
[align=left]Sample Input[/align]
3 3 10 20 30 1 2 2 3 1 3 D 3 Q 1 2 Q 2 1 D 2 Q 3 2 C 1 50 Q 1 1 E 3 3 10 20 20 1 2 2 3 1 3 Q 1 1 Q 1 2 Q 1 3 E 0 0
[align=left]Sample Output[/align]
Case 1: 25.000000 Case 2: 16.666667
题意:n个结点,m条边的无向图,每个节点有一个整数权值。
3种操作:
D X,删除id为X的边。输入保证每条边至多被删除一次。
Q X k , 计算与结点X联通的结点中(包括X),第K大的权值。如果不存在,输出0。
C X V,把结点X的权值改为V
输出所有询问的平均值。
题解:离线操作,我们把操作倒过来,把删边操作转换为加边。由于要询问第K大,所以我们用平衡树维护一个联通块中的点。当我们要合并两个联通块时,将结点数小的平衡树中的点加入另一个平衡树,删除结点数小的平衡树,这样的合并称为启发式合并。我们来分析一下复杂度,由于1个点合并以后,它所在的树的范围至少增大一倍。所以这个点最多合并logn次,每次合并的复杂度为logn,所以合并的总复杂度为O(n*logn*logn)。单次询问和修改的复杂度为logn。
代码如下:
#include<stdio.h> #include<iostream> #include<algorithm> #include<map> #include<string.h> #include<vector> #define nn 21000 #define mod 100003 typedef long long LL; typedef unsigned long long LLU; const double eps=1e-8; using namespace std; int n,m; int a[nn]; struct node { char c; int x,k; }ask[nn*30]; int u[nn*3],v[nn*3]; bool use[nn*3]; int fa[nn]; struct node1 { int val; int key; int num; int sum; node1* son[2]; }; node1* Tree[nn]; void update(node1* id) { if(id==NULL) return ; id->sum=id->num; if(id->son[0]!=NULL) id->sum+=id->son[0]->sum; if(id->son[1]!=NULL) id->sum+=id->son[1]->sum; } void Rotate(node1* &id,int d) { node1* tem=id->son[d]; id->son[d]=tem->son[d^1]; tem->son[d^1]=id; update(id); update(tem); id=tem; } void Insert(node1* &id,int val) { if(id==NULL) { id=new node1; id->val=val; id->key=rand()*rand(); id->num=id->sum=1; id->son[0]=id->son[1]=NULL; return ; } if(id->val==val) { id->num++; id->sum++; } else if(val<id->val) { Insert(id->son[0],val); update(id); if(id->son[0]->key<id->key) { Rotate(id,0); } } else { Insert(id->son[1],val); update(id); if(id->son[1]->key<id->key) { Rotate(id,1); } } } void Remove(node1* &id,int val) { if(id==NULL) return ; if(id->val==val) { if(id->num==1) { if(id->son[0]==NULL) { node1* tem=id; id=id->son[1]; delete tem; } else if(id->son[1]==NULL) { node1* tem=id; id=id->son[0]; delete tem; } else { if(id->son[0]->key<id->son[1]->key) { Rotate(id,0); Remove(id->son[1],val); } else { Rotate(id,1); Remove(id->son[0],val); } } } else id->num--; } else if(id->val>val) Remove(id->son[0],val); else Remove(id->son[1],val); update(id); } int Kth(node1* id,int k) { if(id==NULL||k<=0||k>id->sum) return 0; int tem=0; if(id->son[1]!=NULL) tem+=id->son[1]->sum; if(tem>=k) { return Kth(id->son[1],k); } else if(tem+id->num>=k) { return id->val; } else return Kth(id->son[0],k-tem-id->num); } int findfa(int x) { if(fa[x]==x) return x; return fa[x]=findfa(fa[x]); } void Union(node1* &id,int y) { if(id==NULL) return ; Union(id->son[0],y); Union(id->son[1],y); for(int i=0;i<id->num;i++) { Insert(Tree[y],id->val); } delete id; id=NULL; } void Clear(node1* &id) { if(id==NULL) return ; Clear(id->son[0]); Clear(id->son[1]); delete id; id=NULL; } int main() { int i; char s[5]; int cas=1; while(scanf("%d%d",&n,&m)&&(n+m)) { memset(use,false,sizeof(use)); for(i=1;i<=n;i++) { scanf("%d",&a[i]); } for(i=1;i<=m;i++) { scanf("%d%d",&u[i],&v[i]); } int la=0; while(1) { scanf("%s",s); if(s[0]=='E') break; la++; ask[la].c=s[0]; if(s[0]=='D') { scanf("%d",&ask[la].x); use[ask[la].x]=true; ask[la].k=-1; } else { scanf("%d%d",&ask[la].x,&ask[la].k); if(s[0]=='C') { int tem=a[ask[la].x]; a[ask[la].x]=ask[la].k; ask[la].k=tem; } } } for(i=1;i<=n;i++) { fa[i]=i; Tree[i]=NULL; Insert(Tree[i],a[i]); } for(i=1;i<=m;i++) { if(!use[i]) { int fx=findfa(u[i]); int fy=findfa(v[i]); if(fx!=fy) { if(Tree[fx]->sum<Tree[fy]->sum) { fa[fx]=fy; Union(Tree[fx],fy); } else { fa[fy]=fx; Union(Tree[fy],fx); } } } } double ans=0; int q=0; for(i=la;i>=1;i--) { if(ask[i].c=='D') { int fx=findfa(u[ask[i].x]); int fy=findfa(v[ask[i].x]); if(fx!=fy) { if(Tree[fx]->sum<Tree[fy]->sum) { fa[fx]=fy; Union(Tree[fx],fy); } else { fa[fy]=fx; Union(Tree[fy],fx); } } } else if(ask[i].c=='Q') { q++; ans+=Kth(Tree[findfa(ask[i].x)],ask[i].k); } else { int ix=findfa(ask[i].x); Remove(Tree[ix],a[ask[i].x]); a[ask[i].x]=ask[i].k; Insert(Tree[ix],ask[i].k); } } for(i=1;i<=n;i++) { Clear(Tree[i]); } printf("Case %d: %.6lf\n",cas++,double(ans)/q); } return 0; }
相关文章推荐
- hdu 3726 Graph and Queries(splay查询第k大,启发式合并,删除操作)
- HDU 3726 Graph and Queries Treap
- hdu 3726 Graph and Queries (Treap应用,名次树)
- hdu3726 Graph and Queries(离线+平衡树启发式合并)
- HDU 3726 Graph and Queries (离线处理+splay tree)
- HDU 3726 Graph and Queries 离线处理 treap + 并查集
- HDU 3726 Graph and Queries
- Hdu 3726 Graph and Queries(删边,查询第k大,修改点值)
- HDU 3726 Graph and Queries 平衡树+前向星+并查集+离线操作+逆向思维 数据结构大综合题
- HDU 3726 Graph and Queries splay 离线 模拟
- hdu 3726 Graph and Queries , 天津 2010, LA 5031,并查集,Treap,离线处理
- hdu 3726 Graph and Queries 名次树
- 【HDU】3726 Graph and Queries
- hdu 3726 Graph and Queries 名次树
- HDU 3726 Graph and Queries(treap)
- HDU 3726 Graph and Queries(平衡二叉树)(2010 Asia Tianjin Regional Contest)
- hdu 3726 Graph and Queries 10天津赛区 离线算法+treap维护名次树
- hdu 3726 Graph and Queries
- HDU 3726 Graph and Queries (Treap)