(画师当然是武内崇啦)

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
4 3
1 2 2 1
2
1 2 1
2
Sample Output
3
1

最近在复习数据结构,本来打算找一道平衡树的题来做,在黄学长的博客里看到这道题。结果发现和平衡树其实没有关系。。。

看到这个题的第一想法是暴力:每次o(n)修改或查询
然而o(n^2)肯定会爆(虽然题目不给范围神坑)。我们希望能够通过某些手段来降log。首先是想到线段树,因为线段树可以解决区间内连续色段,但是我们发现这道题是针对整个序列而言,且修改无法用线段树优化。

那怎么办呢?我们发现这道题是将所有颜色为x的改为y,总共有效的修改数量是初始时的颜色种数(最多n)。其实这相当于将颜色x与颜色y合并,且之后不会再拆开。所以说这就是合并的问题啦~(废话了这么久。。)

但是该如何合并呢?我们将同一种颜色的布丁用链表连起来,合并的时候是o(1)的。但是对于合并时ans的更新是o(n)的(对于每一个都判断修改后是否与左右连接)。总的来说,就是每次合并时的复杂度“被修改的颜色的布丁个数”。

这个是可以优化的,就是用启发式合并(把小的往大的合并)。这样就是o(nlogn)的了。证明就搬一下黄学长的;

1:每次O(N)
2:每次合并后,队列长度一定大于等于原来短的长度的两倍。
这样相当于每次合并都会让短的长度扩大一倍以上,
最多扩大logN次,所以总复杂度O(NlogN),每次O(logN)。

但是由于为了启发式合并,我们改变了合并方向。需要用一个f[i]数组来存 调用i颜色时真正用到的颜色。

下面谈谈链表:
我以前一直都不清楚链表到底是个什么货。现在好像是明白了:
有两种链表:
1、对于每个点,有一个pre(前继)和nxt(后继)。这相当于双向链表
2、记录一个链表的开头head,对每个点记录一个nxt(下一个)。这相当于是单向链表

这道题需要访问链表的全部元素,所以用第二种链表。

(其实之前接触过这链表很多次,但一直不知道这就是链表)

放代码啦:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;const int N=1000000+5;int n,m,c[N],siz[N],f[N],ans=0;
int head[N],nxt[N],st[N];void solve(int a,int b){for(int i=head[a];i;i=nxt[i]){if(c[i+1]==b) ans--;if(c[i-1]==b) ans--;}for(int i=head[a];i;i=nxt[i]) c[i]=b;/*这是两种不同的合并方式*/
//  nxt[st[a]]=head[b];head[b]=head[a];nxt[st[b]]=head[a];
//  head[a]=0,st[a]=0;st[b]=st[a];
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",&c[i]);siz[c[i]]++,f[c[i]]=c[i];if(c[i]!=c[i-1]) ans++;if(!head[c[i]]) st[c[i]]=i;nxt[i]=head[c[i]],head[c[i]]=i;}int opt,x,y;while(m--){scanf("%d",&opt);if(opt==2) printf("%d\n",ans);else{scanf("%d%d",&x,&y);if(x==y) continue;//if(siz[f[x]]==0) continue;if(siz[f[x]]>siz[f[y]]) swap(f[x],f[y]);if(siz[f[x]]==0) continue;siz[f[x]]+=siz[f[y]],siz[f[x]]=0;//+=solve(f[x],f[y]);}}return 0;
}

转载于:https://www.cnblogs.com/LinnBlanc/p/7763119.html

【bzoj1486】【[HNOI2009]梦幻布丁】启发式链表合并(详解)相关推荐

  1. P3201 [HNOI2009]梦幻布丁 [启发式合并][set]

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

  2. P3201 [HNOI2009] 梦幻布丁 启发式合并

    P3201 [HNOI2009] 梦幻布丁 考察:启发式合并,set 思路: 这种不可逆的改变都应该采用启发式合并,即把集合大小小的合并到大的去.那么要统计cnt,遍历小的集合中的每个元素,它前面的那 ...

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

    1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 3323  Solved: 1304 [Submit][Sta ...

  4. java 链表逆转_java 实现单链表逆转详解及实例代码

    java 实现单链表逆转详解 实例代码: class Node { Node next; String name; public Node(String name) { this.name = nam ...

  5. HTML---表格合并(详解)

    例子详解: 关键字解释: border="1" :表格标签默认是无边框的,所以这里加上border="1"是为了更好的进行样式展示: colspan=" ...

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

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

  7. ac 梦幻布丁 启发式合并

    题意:中文题. 对于每种颜色,我们都可以看成一个集合.让后把一种颜色变成另一种颜色就转换成了把两个集合的合并问题.显然我们有一个复杂度为O(NlogN)O(NlogN)O(NlogN)的启发式合并能完 ...

  8. [HNOI2009]梦幻布丁

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

  9. 启发式合并详解 (基于CF 1620E - Replace the Numbers)

    前言: 这是Educational Codeforces Round 119 (Rated for Div. 2)的第五题, 这个题我最开始使用从后往前的方法写的,复杂度 O(n)O(n)O(n). ...

最新文章

  1. Hibernate的条件查询的几种方式
  2. 一周飞越50万平方米,无人机检测1.5吨海滩垃圾!自动分类47种,准确率超95%
  3. 给互联网巨头“搬砖”的人
  4. 《R语言实战》读书笔记--第一章 R语言介绍
  5. 【OPENGL】第三篇 着色器基础(一)
  6. 手把手教你玩转SOCKET模型之重叠I/O篇(下)
  7. 关于OpenMesh在Vs2008下编译与安装
  8. MySQL主键的理解
  9. Python实现八皇后问题所有实现方式
  10. 用GCD线程组与GCD信号量将异步线程转换为同步线程
  11. python文件头--文件编码指定
  12. python实现关键词提取
  13. android 广告close,小程序广告弹出与关闭
  14. 招人啦!安卓/Java/数据库/测试等一大波岗位袭来
  15. 区块链技术人才严重不足,平均薪资 2.58 万
  16. JavaScript 是按值传递还是按引用传递的
  17. Canvas旋转元素
  18. vulhub Tomcat8漏洞复现
  19. Access的BOM开发(2)基础信息
  20. 深度学习-22:信息论和信息熵

热门文章

  1. linux中的httpd源码安装方法
  2. ccna____总结
  3. 交换机二层交换和三层交换技术比较
  4. .net3.5下使用LINQ递归算法实现简洁代码
  5. DateChooser ASP.NET 2.0版 之实用版
  6. Final Cut Pro快捷键
  7. 我希望你能精简一些东西
  8. Linux rsync 命令参数详解
  9. undefined和null
  10. Python - 列表与字符串的互相转换