bzoj 1483 [HNOI2009]梦幻布丁(链表+启发式合并)
1483: [HNOI2009]梦幻布丁
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 1818 Solved: 761
[Submit][Status][Discuss]
Description
N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色.
Input
第
一行给出N,M表示布丁的个数和好友的操作次数.
第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,对于每个操作,若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表
示将所有颜色为X的变为Y,X可能等于Y. 若第一个数字为2表示要进行询问当前有多少段颜色,这时你应该输出一个整数. 0
Output
针对第二类操作即询问,依次输出当前有多少段颜色.
Sample Input
1 2 2 1
2
1 2 1
2
Sample Output
1
【思路】
链表+启发式合并。
每种颜色设一个链表,并记下段数ans。
对于修改,先假设不变,如果左,右不一样则ans--,然后修改颜色值,再遍历一次,如果不一样则ans++,这样就只有因为颜色相同而并成一块的会ans—了。具体修改成哪一个颜色对题目并没有影响,所以采用启发式合并,每次将颜色数少的设为颜色数多的,合并后的总长度一定大于较短的两倍,我们每次都是操作较短的,每次合并长度都会扩大两倍以上最多扩大logn次,时间复杂度为O(nlogn)。
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int M = 1e6+; int n,m,a[M],num[M],next[M],front[M],p[M],ans=; int main() {
scanf("%d%d",&n,&m);
memset(front,-,sizeof(front));
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
num[a[i]]++;
}
for(int i=;i<=n;i++){
next[i]=front[a[i]];
front[a[i]]=i;
}
for(int i=;i<=n;i++)
if(a[i]!=a[i-]) ans++;
for(int i=;i<=M-;i++) p[i]=i;
for(int j=;j<=m;j++) {
int op,x,y;
scanf("%d",&op);
if(op==)
printf("%d\n",ans);
else {
scanf("%d%d",&x,&y);
if(x==y) continue;
if(num[p[x]]>num[p[y]]) swap(p[x],p[y]);
x=p[x]; y=p[y];
if(num[x]==) continue;
for(int i=front[x];i!=-;i=next[i]){
if(a[i]!=a[i-]) ans--;
if(a[i]!=a[i+]&&i!=n) ans--;
}
for(int i=front[x];i!=-;i=next[i]) a[i]=y;
int head;
for(int i=front[x];i!=-;i=next[i]) {
if(a[i]!=a[i-]) ans++;
if(a[i]!=a[i+]&&i!=n) ans++;
head=i;
}
num[y]+=num[x]; num[x]=;
next[head]=front[y]; front[y]=front[x];
front[x]=-;
}
}
return ;
}
bzoj 1483 [HNOI2009]梦幻布丁(链表+启发式合并)的更多相关文章
- BZOJ 1483: [HNOI2009]梦幻布丁( 链表 + 启发式合并 )
把相同颜色的串成一个链表, 然后每次A操作就启发式合并, 然后计算对答案的影响. ----------------------------------------------------------- ...
- BZOJ 1483: [HNOI2009]梦幻布丁 [链表启发式合并]
1483: [HNOI2009]梦幻布丁 题意:一个带颜色序列,一种颜色合并到另一种,询问有多少颜色段 一种颜色开一个链表,每次遍历小的合并到大的里,顺带维护答案 等等,合并方向有规定? 令col[x ...
- bzoj 1483: [HNOI2009]梦幻布丁 (链表启发式合并)
Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色. 例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input ...
- [BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并)
[BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并) 题面 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1 ...
- 【BZOJ1483】[HNOI2009]梦幻布丁 链表+启发式合并
[BZOJ1483][HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2 ...
- 洛谷P3201 [HNOI2009]梦幻布丁(链表 + 启发式合并)
题目链接 给出 \(n\) 个布丁,每个补丁都有其颜色.现在有 \(m\) 次操作,每次操作将第 \(x_i\) 种颜色全部变为第 \(y_i\) 种颜色. 操作中可能会插入询问,回答目前总共有多少段 ...
- bzoj1483: [HNOI2009]梦幻布丁(链表+启发式合并)
题目大意:一个序列,两种操作. ①把其中的一种数修改成另一种数 ②询问有多少段不同的数如1 2 2 1为3段(1 / 2 2 / 1). 昨晚的BC的C题和这题很类似,于是现学现写居然过了十分开心. ...
- bzoj 1483: [HNOI2009]梦幻布丁 启发式合并vector
1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec Memory Limit: 64 MB[Submit][Status][Discuss] Description N个 ...
- bzoj 1483: [HNOI2009]梦幻布丁
1483: [HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1 ...
随机推荐
- [CSS]font- 属性
所有浏览器都支持 font 属性. 注释:任何的版本的 Internet Explorer (包括 IE8)都不支持属性值 "inherit". 定义和用法 font 简写属性在一 ...
- 【InstallShield】 为什么卸载后有的文件没有删掉
1.Component的属性Permanent设置为Yes. 2.Component的ID为空. 3.Component被其他应用程序或者Feature使用. 4.设置了一个Condition,在安装 ...
- c语言通过89C51驱动1602液晶显示(入门级别)
工具proteus,keil 步骤: 1.画好电路图 2.在指令模式下,设置好显示模式以及光标位置 3.在写数据模式下,向1602写入显示字符(1602只能显示数字和字符) 电路图 #include ...
- 史上最全github使用方法:github入门到精通--备用
[初识Github] 首先让我们大家一起喊一句“Hello Github”.YEAH!就是这样. Git是一个分布式的版本控制系统,最初由Linus Torvalds编写,用作Linux内核代码的管理 ...
- Grails连接外部数据库注意事项Could not determine Hibernate dialect for database name [Oracle]!
初次使用Grails时,使用其内置数据库,一直不会出错,但迁移到外部数据库时会出错Could not determine Hibernate dialect for database name [Or ...
- AMH4.2免费版手动编译升级Nginx1.8版本方法
从AMH免费版本停留在4.2版本之后就没有进行更新和升级,而且官方提供的解决文档也比较少,毕竟免费且没有盈利的产品还是没有多少兴趣的.但是,对于大部分网站环境来说,安装和使用AMH4.2免费版本还是够 ...
- BZOJ 3929 Circle of digits 解题报告
首先,我们可以得到最高位的位数为:\(\lfloor\frac{n+k-1}{n}\rfloor\),记作 \(E\). 然后给这 \(n\) 个长为 \(E\) 的数字排序,后缀数组 \(O((n+ ...
- 关于.net那点事儿
.NET是什么? .NET是开发“托管”软件的平台. 传统环境和.NET环境区别: 传统环境——先将源代码编译为包含机器代码的可执行文件,然后由操作系统加载和执行可执行文件. .NET环境——编译器首 ...
- 物理地址为20位 如10000H 用段地址*16+偏移地址表示
段地质在cpu中,为16位 段地质*16则变成物理首地址20位,这个物理首地址必定是16的倍数. 偏移地址16位, 则表明一个段的大小为64k. 同时也表明16位地址的寻址能力为64kb
- 驱动开发 - WDK 调试及 SVN 环境搭建
由于从公司辞职了,所以以前在公司里搭建的驱动开发环境也就 Game Over 了, 同样由于那环境是很久以前搭建的,自己也有很多记不清楚的地方了, 而且其中还是有很多需要注意的地方的,所以在这里顺便做 ...