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. iOS交互h5— JavaScriptCore ---UIWebview

    JavaScriptCore这个框架,从而让web页面和本地原生应用交互起来非常方便,而且使用此框架可以做到Android那边和iOS相对统一, web前端 在三端交互中,web前端开发人员来定义,让 ...

  2. SpringBoot(四) Core Features: Logging

    参考 文档: 26. Logging

  3. JDBC程序优化--提取配置信息放到属性文件中

    JDBC程序优化--提取配置信息放到属性文件中 此处仅仅优化JDBC连接部分,代码如下: public class ConnectionFactory { private static String ...

  4. div模拟textarea文本域轻松实现高度自适应——张鑫旭

    by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=1362 一.关于tex ...

  5. NOIP2017 题解

    QAQ--由于没报上名并没能亲自去,自己切一切题聊以慰藉吧-- 可能等到省选的时候我就没有能力再不看题解自己切省选题了--辣鸡HZ毁我青春 D1T1 小凯的疑惑 地球人都会做,懒得写题解了-- D1T ...

  6. Spring 框架学习—控制反转(IOC)

        Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建. 简单来说,Spring是一个分层的JavaSE/EEfull-st ...

  7. 微信小程序“满月”:尝鲜之后你还用过它吗?

    距离 2017 年 1 月 9 日微信小程序上线,整整过去了一个月时间.和互联网时代每天出现的众多新鲜事物相似,小程序甫一诞生,立即占据了各大科技媒体网站头屏并引起社交圈的兴奋讨论.由于背靠微信,纷纷 ...

  8. Oracle获取session的trace

    1. 使用参数SQL_TRACE 下面是官网对此参数的说明 SQL_TRACE Property Description Parameter type Boolean Default value fa ...

  9. 7 Recursive AutoEncoder结构递归自编码器(tensorflow)不能调用GPU进行计算的问题(非机器配置,而是网络结构的问题)

    一.源代码下载 代码最初来源于Github:https://github.com/vijayvee/Recursive-neural-networks-TensorFlow,代码介绍如下:“This ...

  10. Two tomcat 冲突

    一.一般修改 路径: /opt/apache-tomcat/conf/server.xml 1.第一个tomcat使用默认配置 2.第二个tomcat一般配置 二.特殊修改 1.第二个tomcat特殊 ...