【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;
}
【HNOI2009】梦幻布丁的更多相关文章
- bzoj 1483 [HNOI2009]梦幻布丁(链表+启发式合并)
		1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1818 Solved: 761[Submit][Status ... 
- BZOJ 1483: [HNOI2009]梦幻布丁( 链表 + 启发式合并 )
		把相同颜色的串成一个链表, 然后每次A操作就启发式合并, 然后计算对答案的影响. ----------------------------------------------------------- ... 
- BZOJ 1483: [HNOI2009]梦幻布丁 [链表启发式合并]
		1483: [HNOI2009]梦幻布丁 题意:一个带颜色序列,一种颜色合并到另一种,询问有多少颜色段 一种颜色开一个链表,每次遍历小的合并到大的里,顺带维护答案 等等,合并方向有规定? 令col[x ... 
- [HNOI2009] 梦幻布丁
		[HNOI2009] 梦幻布丁 标签: 链表 题解 可以直接用链表启发式合并做. 合并的细节处理稍微有点麻烦. 假如需要变成另一种颜色的那个颜色的个数更多,那么就肯定不能直接合. 维护一个color数 ... 
- bzoj 1483: [HNOI2009]梦幻布丁 启发式合并vector
		1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec Memory Limit: 64 MB[Submit][Status][Discuss] Description N个 ... 
- 1483: [HNOI2009]梦幻布丁
		1483: [HNOI2009]梦幻布丁 链接 分析: 启发式合并+链表. 代码: #include<cstdio> #include<algorithm> #include& ... 
- 洛谷 3201 [HNOI2009]梦幻布丁 解题报告
		3201 [HNOI2009]梦幻布丁 题目描述 \(N\)个布丁摆成一行,进行\(M\)次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为\(1,2,2 ... 
- bzoj 1483: [HNOI2009]梦幻布丁
		1483: [HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1 ... 
- BZOJ 1483:[HNOI2009]梦幻布丁(链表+启发式合并)
		[HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一 ... 
- 【BZOJ1483】[HNOI2009]梦幻布丁 链表+启发式合并
		[BZOJ1483][HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2 ... 
随机推荐
- tomcat的8088端口被占用
			打开Dos:windows->输入cmd(想必这个都会) 在黑窗口中输入指令:netstat -ano | findstr 8080 指令的意思是找出占用8080端口的进程pid 再 ... 
- 最近在研究asp.net mvc
			看了很多大牛写的博客,依然对mvc云里雾里. 有一点是毋庸置疑的C应该是一座桥梁建立在model和view之间. 在ASP.NET MVC中,控制器通常是继承System.Web.Mvc.Contro ... 
- MySQL---1、介绍
			一.MySQL简介 1.MySQL简介 MySQL是一个轻量级关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司.目前MySQL被广泛地应用在Internet上的中小型网站 ... 
- Vue 2.0的学习笔记:Vue的过滤器
			转自: https://www.w3cplus.com/vue/how-to-create-filters-in-vuejs.html 过滤器的介绍 1.在Vue中使用过滤器(Filters)来渲染数 ... 
- ASP.NET 简单的柱形图实现(附带示例)
			对于一些内部系统的项目,各种图表是在所难免的,因为图表可以更加清晰的表达出想看到的数据. 因为之前从来没有做过关于图表的东西,唯一能想到的就是“验证码”,所以应该是一个思路,用GDI去搞. 数据懒着去 ... 
- 常见IT英语单词
			lable标签,master精通.主人,reference参考,release发布,schema模式,component组件,persistence持久化,generate生成产生,plugin插件, ... 
- nginx 安装配置和常用命令
			基本环境:CentOS 1. 下载 nginx [root@localhost ~]# cd Downloads/ [root@localhost Downloads]# wget http://ng ... 
- CentOS-Linux系统下安装JDK
			一般情况下,Linux系统都有自带的JDK,但不符合开发要求,所以需要卸载,重新安装JDK 步骤1:查看现有安装的JDK版本 命令: rpm -qa | grep -i java 步骤2:卸载已有软件 ... 
- JDBC入门(1)—— 入门案例
			JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组 ... 
- 手写堆优化dijkstra
			\(dijkstra\) 算法的堆优化,时间复杂度为\(O(n+m)\log n\) 添加数组\(id[]\)记录某节点在堆中的位置,可以避免重复入堆从而减小常数 而这一方法需要依托手写堆 #incl ... 
