【HNOI2009】梦幻布丁
题目描述
N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色。
输入输出格式
输入格式
第一行给出N,M表示布丁的个数和好友的操作次数. 第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,对于每个操作,若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表示将所有颜色为X的变为Y,X可能等于Y. 若第一个数字为2表示要进行询问当前有多少段颜色,这时你应该输出一个整数. 0
输出格式
针对第二类操作即询问,依次输出当前有多少段颜色.
数据范围
\(1\le n,m\le100,000\); \(0<A_i,x,y<1,000,000\)
题解
起初用的线段树维护,可是如果被卡的话,时间复杂度就变成了\(O(n^2log_2n)\)了,所以,看了Hzwer大佬的博客后知道要用链表来解决,我们可以发现,对于一种颜色的操作,是把所有相同颜色都进行改变,所以我们把每种颜色都开一条链来维护,对于每次操作都是将两条链合并,一般的合并时间复杂度是\(O(n)\)的,所以我们要考虑启发式合并,每次我们都会使该条链的长度变为原长度的两倍以上,所以,我们最多只会合并\(log_2n\)次,但是,这样我们就会发现,我们每次合并后颜色可能会发生错位,我们需要利用一个数组来记录这种错位。
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005, MAXM = 1000005;
int color[MAXN], ft[MAXM], Head[MAXM], Next[MAXN], Stern[MAXM], Size[MAXM];
int ans = 0;void Merge(int x, int y){for(int i = Head[x]; i != -1; i = Next[i]){if(color[i + 1] == y) ans --;if(color[i - 1] == y) ans --; }for(int i = Head[x]; i != -1; i = Next[i]) color[i] = y;Next[Stern[x]] = Head[y], Size[y] += Size[x], Head[y] = Head[x];Head[x] = -1 ,Stern[x] = Size[x] = 0;return; }int main()
{int opt, x, y;memset(Head, -1, sizeof(Head));int n, m;scanf("%d%d", &n, &m);for(int i = 1; i <= n; ++ i){scanf("%d", &color[i]);ft[color[i]] = color[i];if(color[i] != color[i - 1]) ans ++;if(Head[color[i]] == -1) Stern[color[i]] = i;Next[i] = Head[color[i]], Head[color[i]] = i, Size[color[i]] ++;}for(int i = 1; i <= m; ++ i){scanf("%d", &opt);if(opt == 2) printf("%d\n", ans);else{scanf("%d%d", &x, &y);if(x == y) continue;if(Size[ft[x]] > Size[ft[y]]) swap(ft[x], ft[y]);x = ft[x], y = ft[y];if(Size[x] == 0) continue;Merge(x, y);}}return 0;
}
转载于:https://www.cnblogs.com/2020pengxiyue/p/9564672.html
【HNOI2009】梦幻布丁相关推荐
- P3201 [HNOI2009]梦幻布丁 [启发式合并][set]
P3201 [HNOI2009]梦幻布丁 题意:N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3 ...
- 链表+启发式合并(bzoj 1483: [HNOI2009]梦幻布丁)
1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 3323 Solved: 1304 [Submit][Sta ...
- P3201 [HNOI2009] 梦幻布丁 启发式合并
P3201 [HNOI2009] 梦幻布丁 考察:启发式合并,set 思路: 这种不可逆的改变都应该采用启发式合并,即把集合大小小的合并到大的去.那么要统计cnt,遍历小的集合中的每个元素,它前面的那 ...
- 【bzoj1486】【[HNOI2009]梦幻布丁】启发式链表合并(详解)
(画师当然是武内崇啦) Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3 ...
- [HNOI2009]梦幻布丁
题目描述 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. 第一行给出N,M表示布丁的个 ...
- 【链表+启发式合并】Bzoj1483 [HNOI2009] 梦幻布丁
Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input 第 ...
- 【启发式合并】梦幻布丁(金牌导航 启发式合并-1/luogu 3201)
梦幻布丁 金牌导航 启发式合并-1 luogu 3201 题目大意 有若干个布丁,给出它们的颜色,每次将一个颜色的所有布丁变成另一种颜色,然后询问有多少段连续的数 输入样例 4 3 1 2 2 1 2 ...
- 【BZOJ1483】【codevs2335】【hdu5997】梦幻布丁+加强版,LCA+主席树
传送门1 传送门2 传送门3 思路: 这还要从上一周的BC说起-- 因为正好放大周,在家里颓了一天后准备BC#90 干完两个签到题以后开始搞T3 抽象了很久YY出来一个并查集+主席树 连蒙带骗写了一发 ...
- HYSBZ 1483 梦幻布丁
HYSBZ 1483 梦幻布丁 模拟链表,链表启发式合并 题意 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的 ...
- 【金牌导航】【洛谷 P3201】【启发式合并】梦幻布丁
[金牌导航][洛谷 P3201][启发式合并]梦幻布丁 题目 解题思路 启发式合并真的就是想到挺难的,想到后简单得很 如何判断有几段还是很容易的,如果和前一个布丁颜色不同,段数+1 将每一种颜色看作一 ...
最新文章
- word-break:break-all和 word-wrap:break-word区别
- ubuntu编译内核重启出现:gave up waiting for root device
- leetcode 25. Reverse Nodes in k-Group | 25. K 个一组翻转链表(Java)
- c语言删除数组重复元素并升序,C语言编程题: 编写函数,从一个已经排序的数组中删去某数后,该数组仍然有序....
- React:开发者友好性和易用性
- 用iArduino app+以太网插板实现“iPhone,iPadiPod无线控制Arduino”!
- 原生JS实现Ajax下载文件
- Code blocks调试教程
- vb调用python函数_vb.net / C# 调用 python
- 什么是ARP协议,如何查看ARP表项、如何配置静态ARP?
- 微信昵称特殊符号入库报错解决方案
- 单模光电转换器怎么接_光纤收发器及其连接方式图解!
- 11.4王者荣耀服务器维护中,4月11日全服不停机更新公告
- 利用谷歌浏览器翻译外文文献 操作记录
- 介绍GBase 8C核心技术
- HCNA期末测试题答案
- ABAP角度看SAP货币和汇率
- idea测试rest api方法(HTTP client in IntelliJ IDEA code editor)
- java 读取dwg_Java 读取 dwg 转换 dxf
- 2008下半年来自百度的博客-002