感觉做得有点复杂了,但是AC了还是。。。爽。。。

题意:给你n个点每个点有一个价值,接下来有m条边,然后是q个操作,每个操作有三种情况:

F X K:寻找与X点直接或间接相连的不小于价值K的最小价值,如果找不到就是0

U X K:将X点价值变为K

E A B:删除点A与点B形成的边

最后求价值总和的平均值

首先我们看F操作和U操作可以使用map解决,因为这是典型的带修改并区间找寻大于等于某值的最小值。然后我们看删边,如果直接删的话,我们需要遍历这一维map然后拆分,时间过不了。因此我们想到使用离线操作倒序添边,然后处理集合合并问题就是并查集的典型题了。

接着我们离线后要把每个E与U都处理后再添边,对于U我们必须保存所有修改的历史,因此使用vector。而m条边中删除E的边,我们需要节约时间。存下总所有边与需要删除的边,然后一起排序后双指针维护添边(因为需要删除的边一定在所有边中出现过,且没有重边)。接着对于维护E,添边后需要把一个父节点并上去,且两个map也要合并,因此我们为了节约合并时间,需要简单的启发式合并。其实就是并查集合并时把个数少的并到个数多的上面。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=<<;
const double Pi=acos(-1.0);
const int Mod=1e9+;
const int Max=;
struct node
{
char typ[];
int u,v;
}add[Max],del[Max],ope[Max];
int fat[Max],ran[Max];//离线添边的并查集
map<int,int> mp[Max];//祖先形成的集合里的元素
vector<int> vec[Max];//存下修改的过程值
int len[Max];
void Init(int n)
{
for(int i=;i<n;++i)
{
ran[i]=;
len[i]=;
vec[i].clear();
mp[i].clear();
fat[i]=i;
}
return;
}
int Find(int x)
{
if(x==fat[x])
return fat[x];
return fat[x]=Find(fat[x]);
}
void UnMap(int x1,int y1)
{
for(map<int,int>::iterator it=mp[x1].begin();it!=mp[x1].end();)
{
if(!mp[y1].count(it->first))
mp[y1][it->first]=it->second;
else
mp[y1][it->first]+=it->second;
mp[x1].erase(it++);//删除
}
return;
}
void Union(int x,int y)
{
int x1=Find(x);
int y1=Find(y);
if(x1==y1)
return;
if(ran[x1]<ran[y1])
{
fat[x1]=y1;//价值合并
ran[y1]+=ran[x1];
UnMap(x1,y1);
}
else
{
fat[y1]=x1;//价值合并
ran[x1]+=ran[y1];
UnMap(y1,x1);
}
return;
}
bool cmp(struct node p1,struct node p2)
{
if(p1.u==p2.u)
return p1.v<p2.v;
return p1.u<p2.u;
}
map<int,int>::iterator it;
double Solve(int n,int m,int q,int cnt,int dig)
{
int coun=;
double ans=0.0;
for(int i=;i<n;++i)
mp[i][vec[i][len[i]]]=;//开始每个集合是自己
sort(add,add+m,cmp);
sort(del,del+cnt,cmp);
del[cnt].u=del[cnt].v=-;
//for(int i=0;i<m;++i)
// printf("%d %d\n",add[i].u,add[i].v);
// printf("OK\n");
// for(int i=0;i<cnt;++i)
//printf("%d %d\n",del[i].u,del[i].v);
for(int i=;i<m;++i)//初始添边
{
if(add[i].u==del[coun].u&&add[i].v==del[coun].v)//两边排序后双指针维护
coun++;
else
{//printf("OK\n");
Union(add[i].u,add[i].v);
}
}
for(int i=q-;i>=;--i)
{
if(ope[i].typ[]=='F')
{
int x1=Find(ope[i].u);
it=mp[x1].lower_bound(ope[i].v);
if(it==mp[x1].end())
ans+=0.0;
else
ans+=it->first;
}
else if(ope[i].typ[]=='E')
Union(ope[i].u,ope[i].v);
else//换价值
{
int x1=Find(ope[i].u);
mp[x1][ope[i].v]--;
if(mp[x1][ope[i].v]==)
mp[x1].erase(ope[i].v);
if(mp[x1].count(vec[ope[i].u][len[ope[i].u]-]))
mp[x1][vec[ope[i].u][--len[ope[i].u]]]++;
else
mp[x1][vec[ope[i].u][--len[ope[i].u]]]=;
}
}//printf("%d\n",dig);
return ans/dig;
}
int main()
{
int n,m,q;
int u,v,c;
int cnt,dig,coun=;
while(~scanf("%d %d %d",&n,&m,&q))
{
Init(n);
dig=cnt=;
for(int i=;i<n;++i)
{
scanf("%d",&c);
vec[i].push_back(c);
}
for(int i=;i<m;++i)
{
scanf("%d %d",&u,&v);
u--,v--;
if(u>v)
swap(u,v);
add[i].u=u;
add[i].v=v;
}
for(int i=;i<q;++i)
{
scanf("%s %d %d",&ope[i].typ,&ope[i].u,&ope[i].v);
if(ope[i].typ[]=='F')
{
dig++;
ope[i].u--;
}
else if(ope[i].typ[]=='E')
{
ope[i].u--,ope[i].v--;
if(ope[i].u>ope[i].v)
swap(ope[i].u,ope[i].v);
del[cnt].u=ope[i].u,del[cnt++].v=ope[i].v;
}
else
{
ope[i].u--;
len[ope[i].u]++;
vec[ope[i].u].push_back(ope[i].v);
}
}
printf("Case %d: %.3f\n",++coun,Solve(n,m,q,cnt,dig));
Init(n);
}
return ;
}

HDU 2419 Boring Game(并查集+map)的更多相关文章

  1. HDU 1811 拓扑排序 并查集

    有n个成绩,给出m个分数间的相对大小关系,问是否合法,矛盾,不完全,其中即矛盾即不完全输出矛盾的. 相对大小的关系可以看成是一个指向的条件,如此一来很容易想到拓扑模型进行拓扑排序,每次检查当前入度为0 ...

  2. hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点)

    hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...

  3. HDU(3560)成环,并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3560 并查集查有几个块,修改了之前我的一个方法(用什么map),直接判断根节点的id是i的个数. 然后 ...

  4. HDU 2473 Junk-Mail Filter 并查集,虚拟删除操作

    http://acm.hdu.edu.cn/showproblem.php?pid=2473 给定两种操作 第一种是合并X Y 第二种是把X分离出来,就是从原来的集合中分离出来,其它的关系不变. 关键 ...

  5. HDU 2473 Junk-Mail Filter(并查集的删除操作)

    题目地址:pid=2473">HDU 2473 这题曾经碰到过,没做出来. .如今又做了做,还是没做出来. ... 这题涉及到并查集的删除操作.想到了设一个虚节点,可是我把虚节点设为了 ...

  6. HDU 5441 离线处理 + 并查集

    题意:给n个节点m条带权值边的无向图.然后q个问题,每次询问点对的数目,点对需要满足的条件是:1)连通:2)其路径的最大权值不能超过询问值. 分析:如果没次询问一次,dfs一次,很可能超时,因此可以用 ...

  7. HDU 4496 D-City (并查集)

    题意:有n个城市,m条路,首先m条路都连上,接着输出m行,第i行代表删除前i行的得到的连通块个数 题解:正难则反,我们反向考虑使用并查集添边.首先每个点都没有相连,接着倒着来边添加边计算,当两个点父节 ...

  8. HDU 5441 Travel (并查集+数学+计数)

    题意:给你一个带权的无向图,然后q(q≤5000)次询问,问有多少对城市(城市对(u,v)与(v,u)算不同的城市对,而且u≠v)之间的边的长度不超过d(如果城市u到城市v途经城市w, 那么需要城市u ...

  9. hdu 2480 贪心+简单并查集

    Steal the Treasure Time Limit: 10000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

随机推荐

  1. java8 关于日期的处理

    Java8 为我们提供了一种新的日期格式:LocalDate和LocalDateTime 获取当前的时间及前一天时间的方法: import java.time.LocalDateTime; impor ...

  2. Cocos2d-x Lua中实例:帧动画使用

    下面我们通过一个实例介绍一下帧动画的使用,这个实例如下图所示,点击Go按钮开始播放动画,这时候播放按钮标题变为Stop,点击Stop按钮可以停止播放动画. 帧动画实例 下面我们再看看具体的程序代码,首 ...

  3. Java+selenium自动化测试基础

    Java+selenium maven配置 maven的配置,但还需要建立maven的本地库,修改apach-maven的setting.xml http://www.cnblogs.com/haoa ...

  4. JavaScript数据结构与算法-集合练习

    集合的实现 function Set () { this.dataStore = []; this.add = add; this.remove = remove; this.size = size; ...

  5. Vue.js之组件嵌套

    Vue.js中组件嵌套有两种方式 第一种:注册全局组件 例如在components文件夹下新建一个User.vue组件,然后在main.js文件中注册全局组件 //注册全局组件 Vue.compone ...

  6. php中定时计划任务的实现原理

    根据php手册简单介绍一些相关的知识: 1.连接处理: 在 PHP 内部,系统维护着连接状态,其状态有三种可能的情况: 0 - NORMAL(正常) 1 - ABORTED(异常退出) 2 - TIM ...

  7. Java关键字this

    Java关键字this只能用于方法方法体内.当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是 this.因此,this只能在类中的非静态方法中使用,静 ...

  8. C#基础之匿名方法实例教程

    本文以实例形式讲解了C#的匿名方法的用法,分享给大家供大家参考之用.具体如下: 匿名方法是C# 2.0的语言新特性.首先看个最简单的例子: class Program { static void Ma ...

  9. NSOperation简介

    1.NSOperation的作用 配合使用NSOperation和NSOperationQueue也能实现多线程编程. 2.NSOperation和NSOperationQueue实现多线程的具体步骤 ...

  10. CSS中input输入框点击时去掉外边框方法【outline:medium;】----CSS学习

    CSS 中添加 outline:medium; JS 控制焦点: $("#CUSTOM_PHONE").focus(function(event){ // this.attr(&q ...