/*好題!
本題的靚處:
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;
}
HDOJ2419-逆向處理操作,並查集,set
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.