/*好题! 本题的靓处: 1.逆向处理所给操作,将集合的拆分化为整合 2.STL set的lower_bound()函数 想法非原创,来自:http://blog.csdn.net/woshi250hua/article/details/7782875 */ #include <cstdio> #include <set> #include <cctype> #include <cstring> #include <iostream> using namespace std; const int NN=20002; const int QQ=300002; int n,m,q,w[NN]; multiset<int> Set[NN]; multiset<int> adj[NN]; int p[NN]; int find(int x) { if (p[x]!=x) p[x]=find(p[x]); return p[x]; } void Union(int x,int y) { multiset<int>::iterator it; x=find(x); y=find(y); if (x==y) return; if (Set[x].size()>Set[y].size()) swap(x,y); //这句优化有从TLE到AC的奇效 p[x]=y; for (it=Set[x].begin(); it!=Set[x].end(); it++) Set[y].insert(*it); Set[x].clear(); //及时释放空间 } int x[QQ],y[QQ]; char ope[QQ]; int main() { int T,cas=0; int a,b,z,fa,fb,fx,fy; multiset<int>::iterator it; while (~scanf("%d%d%d",&n,&m,&q)) { for (int i=1; i<=n; i++) { scanf("%d",&w[i]); Set[i].clear(); p[i]=i; } for (int i=1; i<=m; i++) { scanf("%d%d",&a,&b); if (a<b) adj[a].insert(b);//之前一直用map,出现了内存错误,只好借鉴他人的set写法 else adj[b].insert(a); } for (int i=1; i<=q; i++) { ope[i]=getchar(); while (!isalpha(ope[i])) ope[i]=getchar(); scanf("%d %d",&a,&b); x[i]=a; y[i]=b; if (ope[i]=='E') { if (a<b) adj[a].erase(adj[a].find(b)); else adj[b].erase(adj[b].find(a)); } else if (ope[i]=='U') y[i]=w[a],w[a]=b; } //the final graph for (int i=1; i<=n; i++) Set[i].insert(w[i]); for (int i=1; i<=n; i++) { for (it=adj[i].begin(); it!=adj[i].end(); it++) Union(i,*it); adj[i].clear(); //及时释放空间 } //deal with the operations int cnt=0; double sum=0; for (int i=q; i; i--) { a=x[i]; b=y[i]; if (ope[i]=='F') { fa=find(a); it=Set[fa].lower_bound(b); if (it!=Set[fa].end()) sum+=*it; cnt++; } else if (ope[i]=='U') { fa=find(a); Set[fa].erase(Set[fa].find(w[a])); Set[fa].insert(b); w[a]=b; } else Union(a,b); } printf("Case %d: %.3lf\n",++cas,sum/cnt); } return 0; }