3201 [HNOI2009]梦幻布丁

题目描述

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

输入输出格式

输入格式:

第一行给出\(N,M\)表示布丁的个数和好友的操作次数. 第二行\(N\)个数\(A_1,A_2,\dots,A_n\)表示第\(i\)个布丁的颜色.

从第三行起有\(M\)行,对于每个操作,若第一个数字是\(1\)表示要对颜色进行改变,其后的两个整数\(X,Y\)表示将所有颜色为\(X\)的变为\(Y\),\(X\)可能等于\(Y\).

若第一个数字为\(2\)表示要进行询问当前有多少段颜色,这时你应该输出一个整数.

输出格式:

针对第二类操作即询问,依次输出当前有多少段颜色.

说明

\(1<=n,m<=100,000,0<A_i,x,y<1,000,000\)


思路:对每个颜色维护一个平衡树,平衡树每个节点维护一个是否贡献,我设定的是与前驱是否相邻,然后维护子树贡献和。每次暴力启发式合并就可以了。

听说有链表\(O(n\log n)\)的高级做饭,但是我懒得看。


Code:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <cstdlib>
  4. #define ls ch[now][0]
  5. #define rs ch[now][1]
  6. const int N=1e5+10;
  7. int sum[N],ch[N][2],val[N],d[N],siz[N],root[N*10],n,m;
  8. void updata(int now){sum[now]=sum[ls]+sum[rs]+d[now],siz[now]=siz[ls]+siz[rs]+1;}
  9. void split(int now,int k,int &x,int &y)
  10. {
  11. if(!now){x=y=0;return;}
  12. if(now<=k)
  13. x=now,split(rs,k,rs,y);
  14. else
  15. y=now,split(ls,k,x,ls);
  16. updata(now);
  17. }
  18. int Merge(int x,int y)
  19. {
  20. if(!x||!y) return x|y;
  21. if(val[x]<val[y])
  22. {
  23. ch[x][1]=Merge(ch[x][1],y);
  24. updata(x);
  25. return x;
  26. }
  27. else
  28. {
  29. ch[y][0]=Merge(x,ch[y][0]);
  30. updata(y);
  31. return y;
  32. }
  33. }
  34. void Insert(int id,int now)
  35. {
  36. int x,y,z;
  37. split(root[id],now,x,y);
  38. split(x,now-2,x,z);
  39. sum[now]=d[now]=z==0;
  40. x=Merge(x,z);
  41. split(y,now+1,z,y);
  42. sum[z]=d[z]=0;
  43. y=Merge(z,y);
  44. root[id]=Merge(x,Merge(now,y));
  45. }
  46. void dfs(int id,int now)
  47. {
  48. if(!now) return;
  49. dfs(id,ls),dfs(id,rs);
  50. ls=rs=0,siz[now]=1,Insert(id,now);
  51. }
  52. int ans=0;
  53. void merge(int x,int y)
  54. {
  55. if(x==y) return;
  56. if(siz[root[x]]<siz[root[y]]) std::swap(root[x],root[y]);
  57. ans-=sum[root[x]]+sum[root[y]];
  58. dfs(x,root[y]);
  59. root[y]=0,ans+=sum[root[x]];
  60. }
  61. int main()
  62. {
  63. //freopen("data.in","r",stdin);
  64. //freopen("dew.out","w",stdout);
  65. scanf("%d%d",&n,&m);
  66. for(int clo,i=1;i<=n;i++)
  67. {
  68. scanf("%d",&clo);
  69. val[i]=rand(),siz[i]=1;
  70. Insert(clo,i);
  71. }
  72. for(int i=1;i<=1000000;i++) ans+=sum[root[i]];
  73. for(int op,x,y,i=1;i<=m;i++)
  74. {
  75. scanf("%d",&op);
  76. if(op==1) scanf("%d%d",&x,&y),merge(y,x);
  77. else printf("%d\n",ans);
  78. }
  79. return 0;
  80. }

2018.12.12

洛谷 3201 [HNOI2009]梦幻布丁 解题报告的更多相关文章

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

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

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

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

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

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

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

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

  5. 洛谷_Cx的故事_解题报告_第四题70

    1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h>   struct node {     long x,y,c; ...

  6. 洛谷 P2317 [HNOI2005]星际贸易 解题报告

    P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...

  7. 洛谷 P3802 小魔女帕琪 解题报告

    P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...

  8. 洛谷 P2606 [ZJOI2010]排列计数 解题报告

    P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...

  9. 洛谷1303 A*B Problem 解题报告

    洛谷1303 A*B Problem 本题地址:http://www.luogu.org/problem/show?pid=1303 题目描述 求两数的积. 输入输出格式 输入格式: 两个数 输出格式 ...

随机推荐

  1. Maven学习(三)-----Maven本地资源库

    Maven本地资源库 Maven的本地资源库是用来存储所有项目的依赖关系(插件jar和其他文件,这些文件被Maven下载)到本地文件夹.很简单,当你建立一个Maven项目,所有相关文件将被存储在你的M ...

  2. Scrapy爬去哪儿~上海一日游门票并存入MongoDB数据库

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZwAAAGGCAYAAABPDDfEAAAgAElEQVR4nOy9C3Rb1Z3/+z1Hkm35mT

  3. 003--MySQL 数据库事务

    什么是事务? 事务是一组原子性的 SQL 查询, 或者说是一个独立的工作单元. 在事务内的语句, 要么全部执行成功, 要么全部执行失败. 事务的 ACID 性质 数据库事务拥有以下四个特性, 即 AC ...

  4. HIVE中的数据怎么导出到hdfs或本地呢

    思路一:重定向 在我不知道工具 ,也不熟悉HIQL语法的情况下,没办法了,只有选择一个最简单粗暴的方法,重定向. 在shell中使用 hive -e 可以在shell中执行hive命令,hive -f ...

  5. IncDec序列:差分+贪心

    IncDec序列 题目描述: 给定一个长度为 n 的数列 a1,a2,…,an,每次可以选择一个区间[l,r],使下标在这个区间内的数都加一或者都减一. 求至少需要多少次操作才能使数列中的所有数都一样 ...

  6. linux 命令自动补全包

    linux 其他知识目录 rhel7如果使用最小化安装后,tab键默认是不能自动补全命令的 执行yum install bash-completion之后重启系统正常.

  7. C++ 名字空间namespace的使用

    A namespace is a scope.C++ provides namespaces to prevent name conflicts.A namespace is a mechanism ...

  8. 20135208JAVA第二次试验

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计  班级:1352 姓名:贺邦  学号:20135208 成绩:             指导教师:娄嘉鹏  ...

  9. [pascal入门]数组

    一.本节目标 本节我们将要讲述数组.本节目标: 一维数组 二维数组 字符数组 二.一维数组 我们通过一个案例来简单的理解数组.班主任要计算班级里面50个同学数学成绩的平均成绩,道理上讲这是一个比较简单 ...

  10. ArrayList和LinkedList源码分析

    ArrayList 非线程安全 ArrayList内部是以数组存储元素的.类有以下变量: /*来自于超类AbstractList,使用迭代器时可以通过该值判断集合是否被修改*/ protected t ...