题目链接

给出 \(n\) 个布丁,每个补丁都有其颜色。现在有 \(m\) 次操作,每次操作将第 \(x_i\) 种颜色全部变为第 \(y_i\) 种颜色。

操作中可能会插入询问,回答目前总共有多少段颜色。

$1 \leq n,m \leq 10^5 $

 

考虑稍微暴力点的做法,每次暴力修改颜色,然后如果对于当前的颜色,找到他们所有的位置,假设其中一个为 \(p\) ,那么通过判断 \(p-1,p+1\)位置的颜色是否为 \(y_i\) 即可。

如果这样做,就需要链表来寻找位置。但是这样还是要超时,复杂度可能为 \(O(n^2)\)。

在这里,可以使用启发式合并,即是每次把小范围并到大范围上去,由于小范围中的数每被并一次,范围中的数至少增大一倍,也就是说每个数最后被并 \(\log(n)\) 次,总的复杂度为 \(O(nlogn)\) 的。

但目前考虑到这里还不足以解决问题,因为题目给出的 “\(x_i,y_i\)”不一定满足 \(x_i<y_i\)。

这里的解决方法就是还是将小范围并到大范围,这里中间的判断操作是不影响的,唯一有变化的就是最终的颜色,我们用一个数组来记录一下最终的颜色就可以了。\(f[i]=j\) 的含义就为 \(i\) 颜色目前为颜色为 \(j\) 的链,然后每次找 \(f[i]\) 即可。数组可以解决很多事情~

具体见代码吧:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
int n, m, ans;
int col[N], first[N], nxt[N], head[N], sz[N], f[N];
int now_c[N] ;
void merge(int x, int y) {
for(int i = head[x]; i; i = nxt[i])
ans -= (col[i - 1] == y) + (col[i + 1] == y);
for(int i = head[x]; i; i = nxt[i]) col[i] = y;
nxt[first[x]] = head[y];
head[y] = head[x];
sz[y] += sz[x]; sz[x] = 0; head[x] = 0;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0) ;
cin >> n >> m;
for(int i = 1; i <= n; i++) {
cin >> col[i] ;
f[col[i]] = col[i] ;
if(col[i] != col[i - 1]) ans++ ;
if(!head[col[i]]) first[col[i]] = i;
++sz[col[i]]; nxt[i] = head[col[i]]; head[col[i]] = i ;
}
for(int i = 1; i <= m; i++) {
int op, x, y;
cin >> op;
if(op == 2) cout << ans << '\n';
else {
cin >> x >> y ;
if(sz[f[x]] > sz[f[y]]) swap(f[x], f[y]) ;
if(sz[f[x]] == 0) continue ;
merge(f[x], f[y]) ;
}
}
return 0;
}

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

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

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

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

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

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

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

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

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

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

    题面 luogu 题解 什么是启发式合并? 小的合并到大的上面 复杂度\(O(nlogn)\) 这题颜色的修改,即是两个序列的合并 考虑记录每个序列的\(size\) 小的合并到大的 存序列用链表 但 ...

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

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

  7. 洛谷P3201 [HNOI2009]梦幻布丁

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

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

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

  9. 洛谷 3201 [HNOI2009]梦幻布丁 解题报告

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

随机推荐

  1. spring-session实现分布式集群session的共享(转)

    原文: https://www.cnblogs.com/youzhibing/p/7348337.html HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保 ...

  2. JS特效@缓动框架封装及应用

    | 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.变量CSS样式属性获取/赋值方法 给属性赋值:(既能获取又能赋值) 1)div.style.width 单个赋值:点语法,这个方法比较固定 ...

  3. 2017年第八届蓝桥杯【C++省赛B组】

    1.标题: 购物单 小明刚刚找到工作,老板人很好,只是老板夫人很爱购物.老板忙的时候经常让小明帮忙到商场代为购物.小明很厌烦,但又不好推辞. 这不,XX大促销又来了!老板夫人开出了长长的购物单,都是有 ...

  4. Linux基础入门--06

    简单的文本处理 实验介绍 这一节我们将介绍这几个命令:tr.col.join.paste 1.tr: -d:删除和set1匹配的字符,不是全词匹配也不是按字符顺序匹配 -s:除去指定的连续并重复的字符 ...

  5. 【每日scrum】第一次冲刺day1

    冲刺第一天,明确了自己的任务,数据分析与数据字典.

  6. java的小学生四则运算

    import java.awt.*; import java.awt.event.*; import java.io.FileNotFoundException; import java.io.IOE ...

  7. Enterprise Library 4.1 参考源码索引

    http://www.projky.com/entlib/4.1/Microsoft/Practices/EnterpriseLibrary/AppSettings/Configuration/Des ...

  8. win10频繁提示证书即将过期怎么办

    最近几天每次开机都会提示许可证即将过期 ”Windows+R”打开“运行”窗口,输入“slmgr.vbs -xpr”并点击“确定”,弹出的窗口确实显示过期时间在本月1.29过期 百度各种激活方法后,发 ...

  9. 使用JavascriptExecutor将页面滚动到最底部

    使用如下代码,将页面滚动到最底部 @Test(enabled = true) public void scroll(){ String jsStr="window.scrollTo(0,do ...

  10. 11git更改提交

    .将不必要的文件add .上次提交觉得是错的 .不想改变暂存区内容,只是想调整提交的信息 .版本回滚 git reset HEAD 文件名 移除不必要的添加到暂存区的文件 git reset HEAD ...