[原创]hdu 5997 rausen loves cakes [启发式合并+树状数组/线段数]【杂类+数据结构】
2017-01-15 21:48:17 Tabris_ 阅读数:258
博客爬取于2020-06-14 22:42:09
以下为正文
版权声明:本文为Tabris原创文章,未经博主允许不得私自转载。
https://blog.csdn.net/qq_33184171/article/details/54564954
题目连接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5997
----------------------------------------------------------------.
rausen loves cakes
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
问题描述
rausen喜欢吃蛋糕。某天,他买了nn个蛋糕,每个蛋糕都有一个颜色,用\left[1,1000000 \right][1,1000000]中的整数来表示。rausen将它们从左到右排成一行,然后准备开始吃。
在吃之前,rausen想对蛋糕进行qq个操作。
某些时刻,rausen会把所有颜色为xx的蛋糕替换成颜色为yy的蛋糕。
另一些时刻,rausen会计算一段区间\left[x,y \right][x,y]内颜色的段数,所谓一段颜色,就是指极长的只有一种颜色的区间。例如1 4 4 1 1即为3段颜色。
然而,rausen发现,他并不会统计区间内的颜色段数,无助的rausen伤心地哭了起来(误)。而你为了安慰他,决定帮他解决这个问题。
输入描述
输入包含多组数据。第一行有一个整数TT,表示测试数据的组数,对于每组数据:
第一行输入2个整数nn,qq分别表示蛋糕的数目和操作的数目。
接下来一行nn个正整数,第ii个正整数{a}_{i}a
i
表示第ii个蛋糕的颜色。
接下来qq行,每行3个整数op\left(1\leq op\leq 2 \right)op(1≤op≤2),xx,yy,描述一个操作
对于op=1op=1,表示rausen进行替换操作,将颜色为xx的蛋糕替换成颜色为yy的蛋糕,xx、yy满足\left(1\leq x,y\leq 1000000 \right)(1≤x,y≤1000000),请注意xx可能等于yy。
对于op=2op=2,表示rausen进行计数操作,此时你需要输出区间\left[x,y \right][x,y]内颜色的段数,xx、yy满足\left(1\leq x\leq y\leq n \right)(1≤x≤y≤n)
\left(1\leq T\leq 5 \right)(1≤T≤5),\left(1\leq n\leq {10}^{5} \right)(1≤n≤10
5
),\left(1\leq q\leq {10}^{5} \right)(1≤q≤10
5
)
输出描述
对于每组测试数据的每一个计数操作,单独输出一行表示答案。
输入样例
1
5 3
1 4 4 10 1
2 1 5
1 4 10
2 3 5
输出样例
4
2
----------------------------------------------------------------.
藏了好久终于补了这个,虽然还是感觉有点乱乱的。。。。
首先考虑暴力的把一种颜色替换成另一种颜色,那么这一部分就是$O(n)$
那么考虑将每一种颜色所在的位置记录下来,这样的话就能降到$O(颜色x的个数)$,虽然看着没什么提升,但其实已经提升很大了,
但是考虑$颜色x->颜色y$如果NUM(x) = n-1,NUM(y)=1,那么直接将x替换为y实在是太浪费了,于是可以将y替换成x,这样的话,运算量将大大减少。而且只需要用一个数组映射就能够实现。(这就是启发式合并了。。。)
用树状数组来维护拐点($a_{i} != a_{i+1}$ 那么$a_i$就是一个拐点)
那么来统计区间内的颜色段数就是求区间内的拐点个数+左端点是不是拐点。。
维护这个就是简单的树状数组的操作了,不再赘述,其实用线段是也可以维护的,但是线段树的代码量...
代码中有详细点的注释,可以看看..
附本题代码
------------------------------------------------------------。
# include <bits/stdc++.h> |


