1483. [HNOI2009]梦幻布丁【平衡树-splay】
Description
Input
Output
针对第二类操作即询问,依次输出当前有多少段颜色.
Sample Input
1 2 2 1
2
1 2 1
2
Sample Output
1
学会启发式合并后,其实这个题就是裸题了
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】的更多相关文章
- bzoj 1483 [HNOI2009]梦幻布丁(链表+启发式合并)
1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1818 Solved: 761[Submit][Status ...
- BZOJ 1483: [HNOI2009]梦幻布丁( 链表 + 启发式合并 )
把相同颜色的串成一个链表, 然后每次A操作就启发式合并, 然后计算对答案的影响. ----------------------------------------------------------- ...
- BZOJ 1483: [HNOI2009]梦幻布丁 [链表启发式合并]
1483: [HNOI2009]梦幻布丁 题意:一个带颜色序列,一种颜色合并到另一种,询问有多少颜色段 一种颜色开一个链表,每次遍历小的合并到大的里,顺带维护答案 等等,合并方向有规定? 令col[x ...
- bzoj 1483: [HNOI2009]梦幻布丁 启发式合并vector
1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec Memory Limit: 64 MB[Submit][Status][Discuss] Description N个 ...
- 1483: [HNOI2009]梦幻布丁
1483: [HNOI2009]梦幻布丁 链接 分析: 启发式合并+链表. 代码: #include<cstdio> #include<algorithm> #include& ...
- bzoj 1483: [HNOI2009]梦幻布丁
1483: [HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1 ...
- [BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并)
[BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并) 题面 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1 ...
- bzoj 1483: [HNOI2009]梦幻布丁 (链表启发式合并)
Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色. 例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input ...
- BZOJ 1483 HNOI2009 梦幻布丁 名单+启示录式的合并
标题效果:特定n布丁.每个人都有一个颜色布丁,所有的布丁反复有一定的颜色变化的颜色,颜色反复询问的段数 数据范围:n<=10W 色彩数<=100W 启发式合并名单0.0 从来不写清楚 实际 ...
随机推荐
- 使用pd从数据库逆向生成pdm文件
使用pd从数据库逆向生成pdm文件 好久没更新博客了,最近忙着各种事,捞了点老本行java的一些东西,浑浑噩噩,花了几天时间用java搭建了一个小项目的restful接口,深深觉得这东西论效率被nod ...
- JavaWeb项目WebContent下的资源文件无法引用
JavaWeb项目引用资源的时候尽量使用绝对路径. 作者在帮助同学完善其JavaWeb项目端页面的时候,css样式文件怎么也引用不了. 第一个想到的是:是不是文件路径写错了? 于是,作者换了绝对路径, ...
- SDWebImage实现图片展示、缓存、清除缓存
1. /* 图片显示 */ [self.imageView sd_setImageWithURL:[NSURL URLWithString:urlString]]; [s ...
- DOS窗口带jar包运行java程序
由于工作环境的问题,有过一次这样的测试,需要在DOS窗口运行带有jar包的java程序 编译命令如下: javac -Djava.ext.dirs=./lib Test.java 或 javac -D ...
- Python逐行读取文件内容
更详细的文件按行读取操作可以参考:http://www.cnblogs.com/xuxn/archive/2011/07/27/read-a-file-with-python.html 一行一行得从文 ...
- 移动端Web Meta标签
原文 http://blog.segmentfault.com/jianjian_532633/1190000000654839 添加到推刊 在介绍移动端特有 meta 标签之前,先简单说一下 ...
- 使用JavaScript动态更改CSS样式
在很多情况下,都需要对网页上元素的样式进行动态的修改.在JavaScript中提供几种方式动态的修改样式,下面将介绍方法的使用.效果.以及缺陷. 1.使用obj.className来修改样式表的类名. ...
- thinkphp3.2 success方法和redirect方法
$this->redirect('showlist',array(),3,'添加成功'); $this->success('添加成功',U('showlist'),3);
- zookeeper应用 - FIFO 队列 分布式队列
使用ZooKeeper实现的FIFO队列,这个队列是分布式的. package fifo; import java.util.Collections; import java.util.List; i ...
- Windows远程桌面Debian配置
由于xrdp.gnome和unity之间的兼容性问题,在Debian仍然无法使用xrdp登陆gnome或unity的远程桌面,现象是登录后只有黑白点为背景,无图标也无法操作.使用xrdp只能登录xfc ...