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。
n,m<=1000000

Output

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

Sample Input

4 3
1 2 2 1
2
1 2 1
2

Sample Output

3
1
 
调了一下午终于A掉了qwq……
学会启发式合并后,其实这个题就是裸题了
splay启发式合并,听起来很智能,只不过就是暴力将小splay上的点一个个insert到大splay上
这个题只需要将需要改的颜色的splay合并到目标颜色splay上就好了
(这个程序并没有从小的合并到大的,不过仍然很快,可能是数据太弱了)
只不过程序中有一些小细节需要注意就是了
细节详见code
 
 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N (1000000+100)
using namespace std;
int Size[N],Key[N];//key[i]中存的是编号为i的颜色,用序列的编号大小来建splay,节点里存颜色
int Father[N],Son[N][];
int n,m,Root[N],ans,a[N];
int flag; int Get(int x){return Son[Father[x]][]==x;}
void Update(int x){Size[x]=Size[Son[x][]]+Size[Son[x][]]+;}
void Clear(int x){Key[x]=Father[x]=Son[x][]=Son[x][]=Size[x]=;} void Rotate(int x)
{
int wh=Get(x);
int fa=Father[x],fafa=Father[fa];
Son[fa][wh]=Son[x][wh^];
Father[fa]=x;
if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
Son[x][wh^]=fa;
Father[x]=fafa;
if (fafa) Son[fafa][Son[fafa][]==fa]=x;
Update(fa);
Update(x);
} void Splay(int x,int &root)
{
for (int fa;fa=Father[x];Rotate(x))
if (Father[fa])
Rotate(Get(fa)==Get(x)?fa:x);
root=x;
} void Insert(int x,int color,int &root)
{
if (root==)
{
Size[x]=;
Key[x]=color;
root=x;
return;
}
int now=root,fa=;
while ()
{
fa=now;now=Son[now][x>now];
if (now==)
{
Size[x]=;
Key[x]=color;
Father[x]=fa;
Son[fa][x>fa]=x;
Update(fa);
Splay(x,root);
return;
}
}
} void Change(int x,int &root,int color)//唯一需要注意的函数,参数:(被拆的splay的当前节点,合并到的splay的根,需要改成什么颜色)。按中序遍历将要拆的splay一个个拆掉就好
{
if (Son[x][]) Change(Son[x][],root,color); int rson=Son[x][];//因为下面要clear x这个节点的信息,所以事先存一下
int pre_color=Key[x];//同上
if (!flag && Key[x]!=Key[x-]) flag=+(color==Key[x-]);//☆如果x是连续序列的开始,就把flag改成1。如果不仅是开始,还能和前一个连起来,flag再加一。(flag在连续序列结束的地方会用到)
Clear(x);
Insert(x,color,root);//插入到目标splay中
if (Key[x]==Key[x+]) ans-=;//如果当前是连续序列的结束且这个点能和后面的颜色接上,ans--。
if (Key[x+]!=pre_color) ans-=flag-,flag=;//如果这个点是结束,ans根据开头是否接上判断减不减。flag归零。 if (rson) Change(rson,root,color);
} int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;++i)
{
scanf("%d",&a[i]);
if (a[i]!=a[i-]) ans++;
Insert(i,a[i],Root[a[i]]);
}
int opt,x,y;
for (int i=;i<=m;++i)
{
scanf("%d",&opt);
if (opt==)
{
scanf("%d%d",&x,&y);
if (Root[x]== || x==y) continue;//如果当前颜色没有节点 或者 这次更改前后的颜色是一样的 就不用做了(因为做了会卡)
Change(Root[x],Root[y],y);
Root[x]=;
}
if (opt==) printf("%d\n",ans);
}
}

1483. [HNOI2009]梦幻布丁【平衡树-splay】的更多相关文章

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

    1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1818  Solved: 761[Submit][Status ...

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

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

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

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

  4. bzoj 1483: [HNOI2009]梦幻布丁 启发式合并vector

    1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec  Memory Limit: 64 MB[Submit][Status][Discuss] Description N个 ...

  5. 1483: [HNOI2009]梦幻布丁

    1483: [HNOI2009]梦幻布丁 链接 分析: 启发式合并+链表. 代码: #include<cstdio> #include<algorithm> #include& ...

  6. bzoj 1483: [HNOI2009]梦幻布丁

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

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

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

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

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

  9. BZOJ 1483 HNOI2009 梦幻布丁 名单+启示录式的合并

    标题效果:特定n布丁.每个人都有一个颜色布丁,所有的布丁反复有一定的颜色变化的颜色,颜色反复询问的段数 数据范围:n<=10W 色彩数<=100W 启发式合并名单0.0 从来不写清楚 实际 ...

随机推荐

  1. 14、通过jpa往数据库插数据

    这是接着上一篇写的,在上一篇的基础上添加 Controller @RestController public class HelloController { @Resource private Hel ...

  2. ASP.NET MVC中你必须知道的13个扩展点

         ScottGu在其最新的博文中推荐了Simone Chiaretta的文章13 ASP.NET MVC extensibility points you have to know,该文章为我 ...

  3. 《AlphaGo世纪对决》与周志华《机器学习》观后感

    这两天看了<AlphaGo世纪对决>纪录片与南大周志华老师的<机器学习>,想谈谈对人工智能的感想. 首先概述一下视频的内容吧,AlphaGo与李世石对战的过程大家都有基本的了解 ...

  4. pycharm配置环境

  5. 【学习笔记】--- 老男孩学Python,day13 生成器,生成器函数,各种推倒式和生成器表达式

    1. 生成器和生成器函数 生成器的本质就是迭代器 生成器的三种创建办法: 1.通过生成器函数 2.通过生成器表达式创建生成器 3.通过数据转换   2. 生成器函数: 函数中包含了yield的就是生成 ...

  6. 教程:RSS全文输出,自己动手做。(一)

    这里以PHP版为例,尽量说得通俗点吧,水平实在有限,见谅. 目前我这里所有的获取全文输出的网站大概是三种情况: 要输出的内容集中在一页上,也就是看似列表页的页面里集中了你想要的所有内容,并不需要点击“ ...

  7. 注重结构、语义、用户体验的Tab选项卡

    效果如下图所示: HTML code: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  8. animation 秒简单笔记

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

  9. Android如何使用WebView访问https的网站

    Android中可以用WebView来访问http和https的网站,但是默认访问https网站时,假如证书不被Android承认,会出现空白页面,且不会有任何提示信息,这时我们必须加多一些配置. 此 ...

  10. ahjesus Axure RP 8.0注册码,亲测可用

    ahjesus Axure RP 8.0注册码 ahjesus Axure RP 8.0注册码 用户名:aaa注册码:2GQrt5XHYY7SBK/4b22Gm4Dh8alaR0/0k3gEN5h7F ...