洛谷传送门

开始一个O(n^2)思路,每次每句要改变颜色的点,改变完颜色后重新计算颜色的段数,显然拉闸。

然后呢。。然后就不会了。

看了别人博客,才知道有个叫做启发式合并的东西,就是把小的合并到大的上面,时间复杂度就将为了log级别,额,为啥呢?

反正这样就更快了。

然后对于此题

我们先求出原序列的答案

每一种颜色搞一条链把该色结点串起来,记录下链条尾结点

把一种颜色的染成另一种,很简单把它合并过去,然后处理下对于答案的影响

但是。。。

比如把1染成2,但是s[1]>s[2],这时我们应该将2合并到1的链后面,但是会遇到一个麻烦的问题,就是这个链头是接1下的,也就是说以后找颜色2,发现没有颜色2只有颜色1。。。

于是我们应该开一个数组f,表示我们寻找一种颜色时,实际应该找哪个颜色下的链,遇到上面那种情况要交换f[1]和f[2]

 #include <iostream>
#include <cstdio>
#define maxn 100005 using namespace std; int n, m, maxx, ans;
int a[maxn], next[maxn], head[maxn * ], tail[maxn * ], cnt[maxn * ], f[maxn * ]; int main()
{
int i, j, x, y, opt;
scanf("%d %d", &n, &m);
for(i = ; i <= n; i++)
{
scanf("%d", &a[i]);
f[a[i]] = a[i];
if(a[i] != a[i - ]) ans++;
if(!tail[a[i]]) head[a[i]] = i;
next[i] = tail[a[i]];
tail[a[i]] = i;
cnt[a[i]]++;
}
for(i = ; i <= m; i++)
{
scanf("%d", &opt);
if(opt == )
{
scanf("%d %d", &x, &y);
if(f[x] == f[y]) continue;
if(cnt[f[x]] > cnt[f[y]]) swap(f[x], f[y]);//表头互换
x = f[x], y = f[y];
if(!cnt[x]) continue;
for(j = tail[x]; j; j = next[j])
{
if(a[j - ] == y) ans--;
if(a[j + ] == y) ans--;
}
for(j = tail[x]; j; j = next[j]) a[j] = y;
next[head[x]] = tail[y];//把 x 合并到 y 上
tail[y] = tail[x];
cnt[y] += cnt[x];
head[x] = tail[x] = cnt[x] = ;
}
else printf("%d\n", ans);
}
return ;
}

把 x 插到 y 的后面,所以得写成

next[head[x]] = tail[y];
tail[y] = tail[x];

也可以把 x 插到 y 的前面,写成

next[head[y]] = tail[x];
head[y] = head[x]

[HNOI2009]梦幻布丁(链表+启发式合并)的更多相关文章

  1. BZOJ 1483: [HNOI2009]梦幻布丁( 链表 + 启发式合并 )

    把相同颜色的串成一个链表, 然后每次A操作就启发式合并, 然后计算对答案的影响. ----------------------------------------------------------- ...

  2. 【BZOJ1483】[HNOI2009]梦幻布丁 链表+启发式合并

    [BZOJ1483][HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2 ...

  3. BZOJ 1483: [HNOI2009]梦幻布丁 [链表启发式合并]

    1483: [HNOI2009]梦幻布丁 题意:一个带颜色序列,一种颜色合并到另一种,询问有多少颜色段 一种颜色开一个链表,每次遍历小的合并到大的里,顺带维护答案 等等,合并方向有规定? 令col[x ...

  4. bzoj 1483: [HNOI2009]梦幻布丁 (链表启发式合并)

    Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色. 例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input ...

  5. 洛谷P3201 [HNOI2009]梦幻布丁(链表 + 启发式合并)

    题目链接 给出 \(n\) 个布丁,每个补丁都有其颜色.现在有 \(m\) 次操作,每次操作将第 \(x_i\) 种颜色全部变为第 \(y_i\) 种颜色. 操作中可能会插入询问,回答目前总共有多少段 ...

  6. bzoj1483: [HNOI2009]梦幻布丁(链表+启发式合并)

    题目大意:一个序列,两种操作. ①把其中的一种数修改成另一种数 ②询问有多少段不同的数如1 2 2 1为3段(1 / 2 2 / 1). 昨晚的BC的C题和这题很类似,于是现学现写居然过了十分开心. ...

  7. bzoj1483: [HNOI2009]梦幻布丁(vector+启发式合并)

    1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 4022  Solved: 1640[Submit][Statu ...

  8. BZOJ 1483 梦幻布丁(链表+启发式合并)

    给出一个长度为n的序列.支持两种操作: 1.把全部值为x的修改成y.2.询问序列有多少连续段. 我们可以对于每个值建立一个链表.对于操作1,则可以将两个链表合并. 对于操作2,只需要在每次合并链表的时 ...

  9. [BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并)

    [BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并) 题面 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1 ...

  10. 洛谷P3201 [HNOI2009]梦幻布丁 [链表,启发式合并]

    题目传送门 梦幻布丁 题目描述 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. 输入输 ...

随机推荐

  1. spring中junit 提示Failed to load ApplicationContext

    错误提示: 1:java.lang.IllegalStateException: Failed to load ApplicationContext 2:Error creating bean wit ...

  2. JSP 错误处理方法

    web.xml中配置error-page标签 1.WEB工程中打开 web.xml 文件

  3. JAVA自带的加密算法-MD5\SHA1\BASE64

    需要导入jar包: commons-codec.jar MD5 String str = "abc"; DigestUtils.md5Hex(str); SHA1 String s ...

  4. 开发笔记 - 解决font-awesome等图标在浏览器中的兼容问题

    今天在写前端页面的时候,觉得font-awesome简单实用就上手试了一下,因为font-awesome图标库甚为强大,我就在其css上多做了一些尝试,这一尝试发现了一个致命的问题,当我对i标签进行统 ...

  5. autoHeight # 动态高度添加 用 window.addEventListener('resize', function () {

    动态高度添加 用 window.addEventListener('resize', function () { mounted () { this.init() window.addEventLis ...

  6. JavaScript操作数组。

    1.shift:删除原数组第一项,并返回删除元素的值,原数组为空则返回undefined. 2.unshift:将参数添加到原数组开头,并返回数组的长度. 3.pop:删除原数组最后一项,并返回删除元 ...

  7. Vue之组件的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. SSM框架删除/更新时返回影响条数

    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">    < ...

  9. 从零开始--系统深入学习Android

    http://www.cnblogs.com/tianjian/category/354587.html

  10. 常见的网络命令--ping.hostname

    hostname命令 作用:显示以及设置主机名 一.  显示系统主机名 第一种方式:hostname 第二种方式:cat /etc/sysconfig/ntework 使用举例: 从上面可以看到我的系 ...