bzoj 2120 线段树套平衡树
先吐下槽,改了快一个小时,最后发现是SBT的delete写错了,顿时就有想死的心。。。。。
首先对于这道题,我们应该先做一下他的小问题,bzoj1878,虽然和这道题几乎一点关系没有,
但是能给我们一个思路的启发
我们先考虑没有修改,只有区间询问
内个我下面的糖果是画笔的意思。。。我也不知道咋着题就读错了。。。。
那么对于一个糖果i,假设他的颜色是col,那么我们找到col颜色上一次出现的位置,为color[i],
那么对于一个区间L R里的color值,我们要找不同的颜色,那么假设一种颜色在L R里出现多次
那么这些糖果的color值除了最先出现的以外,剩下的color值都大于等于L,也就是我们要找在区间
L R里的color值比L小的个数就行了。我们可以用线段树套平衡树来比较容易的实现这一过程
//时间复杂度是O(nlog^2(n))的,1878做不了
树套树就相当于维护color数组用的
那么我们在修改一个位置的颜色的时候,假设把位置I的颜色改为y,原来的颜色为x
那么我们需要修改的是
i位置后面第一个颜色为X的color值改为i的color值
I位置的color值改为i前面最后一个颜色为Y的位置
I位置后面第一个颜色为Y的color值改为I
这样就行了,那么我们为了快速找到“I位置后面第一个颜色为X的糖果的位置”,需要对于每种颜色
建一颗平衡树,关键字为位置,只需要找到后继就行了
/**************************************************************
Problem:
User: BLADEVIL
Language: Pascal
Result: Accepted
Time: ms
Memory: kb
****************************************************************/ //By BLADEVIL
type
rec =record
left, right, root :longint;
end; var
n, m :longint;
a :array[..] of longint;
t :array[..] of rec;
c_pred, c_root :array[..] of longint;
color :array[..] of longint;
tot :longint;
b_left, b_right :array[..] of longint;
b_size, b_key :array[..] of longint; procedure left_rotate(var t:longint);
var
k :longint;
begin
k:=b_right[t];
b_right[t]:=b_left[k];
b_left[k]:=t;
b_size[k]:=b_size[t];
b_size[t]:=b_size[b_left[t]]+b_size[b_right[t]]+;
t:=k;
end; procedure right_rotate(var t:longint);
var
k :longint;
begin
k:=b_left[t];
b_left[t]:=b_right[k];
b_right[k]:=t;
b_size[k]:=b_size[t];
b_size[t]:=b_size[b_left[t]]+b_size[b_right[t]]+;
t:=k;
end; procedure maintain(var t:longint;flag:boolean);
begin
if not flag then
begin
if b_size[b_left[b_left[t]]]>b_size[b_right[t]] then
right_rotate(t) else
if b_size[b_right[b_left[t]]]>b_size[b_right[t]] then
begin
left_rotate(b_left[t]);
right_rotate(t);
end else exit;
end else
begin
if b_size[b_right[b_right[t]]]>b_size[b_left[t]] then
left_rotate(t) else
if b_size[b_left[b_right[t]]]>b_size[b_left[t]] then
begin
right_rotate(b_right[t]);
left_rotate(t);
end else exit;
end;
maintain(b_left[t],false);
maintain(b_right[t],true);
maintain(t,true);
maintain(t,false);
end; procedure insert(var t:longint;v:longint);
begin
if t= then
begin
inc(tot);
t:=tot;
b_left[t]:=;
b_right[t]:=;
b_size[t]:=;
b_key[t]:=v;
end else
begin
inc(b_size[t]);
if v<b_key[t] then insert(b_left[t],v) else insert(b_right[t],v);
maintain(t,v>=b_key[t]);
end;
end; procedure build(x,l,r:longint);
var
mid :longint;
i :longint;
begin
t[x].left:=l; t[x].right:=r;
t[x].root:=;
for i:=l to r do insert(t[x].root,color[i]);
if l=r then exit;
with t[x] do mid:=(left+right) div ;
build(*x,l,mid); build(*x+,mid+,r);
end; procedure init;
var
i :longint;
begin
read(n,m);
for i:= to n do read(a[i]);
for i:= to n do
begin
color[i]:=c_pred[a[i]];
c_pred[a[i]]:=i;
end;
for i:= to n do c_root[a[i]]:=;
for i:= to n do
insert(c_root[a[i]],i);
build(,,n);
end; function select(t,v:longint):longint;
begin
if t= then exit();
if b_key[t]>=v then
select:=select(b_left[t],v) else
select:=select(b_right[t],v)+b_size[b_left[t]]+;
end; function query(x,l,r,y:longint):longint;
var
mid :longint;
begin
if (t[x].left=l) and (t[x].right=r) then
begin
query:=select(t[x].root,y);
exit;
end;
with t[x] do mid:=(left+right) div ;
if l>mid then query:=query(x*+,l,r,y) else
if r<=mid then query:=query(x*,l,r,y) else
query:=query(x*,l,mid,y)+query(x*+,mid+,r,y);
end; procedure ask(l,r:longint);
begin
writeln(query(,l,r,l));
end; function delete(var t:longint;v:longint):longint;
begin
dec(b_size[t]);
if (b_key[t]=v) or (v>b_key[t]) and (b_right[t]=) or (v<b_key[t]) and (b_left[t]=) then
begin
delete:=b_key[t];
if (b_left[t]=) or (b_right[t]=) then t:=b_left[t]+b_right[t] else
b_key[t]:=delete(b_left[t],v+);
end else
if v>b_key[t] then delete:=delete(b_right[t],v) else delete:=delete(b_left[t],v);
end; procedure t_change(x,y,z,xx:longint);
var
mid :longint;
begin
delete(t[x].root,y);
insert(t[x].root,z);
if t[x].left=t[x].right then exit;
with t[x] do mid:=(left+right) div ;
if xx>mid then t_change(*x+,y,z,xx) else
t_change(*x,y,z,xx);
end; function pred(t,v:longint):longint;
begin
if t= then exit();
if b_key[t]>=v then pred:=pred(b_left[t],v) else
begin
pred:=pred(b_right[t],v);
if pred= then pred:=b_key[t];
end;
end; function succ(t,v:longint):longint;
begin
if t= then exit(-);
if b_key[t]<=v then succ:=succ(b_right[t],v) else
begin
succ:=succ(b_left[t],v);
if succ=- then succ:=b_key[t];
end;
end; procedure change(x,y:longint);
var
w1, w2, w3 :longint; begin
if a[x]=y then exit;
w1:=a[x];
w2:=pred(c_root[w1],x);
w3:=succ(c_root[w1],x);
if w3<>- then t_change(,x,w2,w3);
delete(c_root[w1],x);
w1:=w2;
w3:=succ(c_root[y],x);
w2:=pred(c_root[y],x);
if w3<>- then t_change(,w2,x,w3);
t_change(,w1,w2,x);
a[x]:=y;
insert(c_root[y],x);
end; procedure main;
var
i :longint;
ch :char;
x, y :longint;
begin
readln;
for i:= to m do
begin
read(ch);
readln(x,y);
if ch='Q' then
ask(x,y) else
change(x,y);
end; end; begin
init;
main;
end.
bzoj 2120 线段树套平衡树的更多相关文章
- bzoj 1901 线段树套平衡树+二分答案查询
我们就建一颗线段树,线段树的每一个节点都是一颗平衡树,对于每个询问来说,我们就二分答案, 查询每个二分到的mid在这个区间里的rank,然后就行了 /************************* ...
- bzoj 2141 线段树套平衡树
用树套树来解决这个问题,存储每个节点的数值是多少,然后交换 对于答案的变更可以讨论下,假设交换的是x,y位置的数x<=y 如果x=y || high[x]=high[y]则对答案没有影响 如果h ...
- BZOJ 3196 线段树套平衡树
(代码无比丑陋) //By SiriusRen #include <cstdio> #include <algorithm> using namespace std; int ...
- bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description ...
- 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2271 Solved: 935[Submit][Stat ...
- CF 19D - Points 线段树套平衡树
题目在这: 给出三种操作: 1.增加点(x,y) 2.删除点(x,y) 3.询问在点(x,y)右上方的点,如果有相同,输出最左边的,如果还有相同,输出最低的那个点 分析: 线段树套平衡树. 我们先离散 ...
- BZOJ3196二逼平衡树——线段树套平衡树(treap)
此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...
- P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)
P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...
- [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...
随机推荐
- BI领军者之一Tableau试用浅谈
下图是最新的Gartner BI Magic Quadrant,其中领军者之一的Tableau表现的异常突出,执行力象限上直接甩开其它产品一条街,前瞻性象限上略微超越了MSBI,怀着无比的好奇心,特意 ...
- Spring实战第六章学习笔记————渲染Web视图
Spring实战第六章学习笔记----渲染Web视图 理解视图解析 在之前所编写的控制器方法都没有直接产生浏览器所需的HTML.这些方法只是将一些数据传入到模型中然后再将模型传递给一个用来渲染的视图. ...
- 梳理 Opengl ES 3.0 (一)宏观着眼
Opengl ES 可以理解为是在嵌入式设备上工作的一层用于处理图形显示的软件,是Opengl 的缩水版本. 下图是它的工作流程示意图: 注意图中手机左边的EGL Layer Opengl ES是跨平 ...
- Android之内容提供者ContentProvider的总结
本文包含以下知识点: ContentProvider Uri 的介绍 ContentResolver: 监听ContentProvider的数据改变 一:ContentProvider部分 Conte ...
- 团队项目-第十次scrum 会议
时间:11.6 时长:20分钟 地点:主235教室走廊 工作情况 团队成员 已完成任务 待完成任务 解小锐 完成多种招聘方式的逻辑编写 陈鑫 实现游戏的存档功能 李金奇 添加多种招聘方式等功能 王辰昱 ...
- Python调用MYSQL,将文件名和路径批量入库用法小结
最近项目需要将大量的压缩文件导入到数据库中,所以开始总结用Python批量处理的办法,本次是首先将这些压缩文件的文件名提取出来,然后导入到数据库中. 由于涉及到路径的读取处理,所以方法有os模块和co ...
- python进制转换(二进制、十进制和十六进制)及注意事项
使用内置函数实现进制转换实现比较简单,主要用到以下函数: bin().oct().int().hex() 下面分别详解一下各个函数的使用(附实例) 第一部分:其他进制转十进制 1.二进制转十进制 使用 ...
- IE浏览器报Promise未定义的错误
背景: 一个vue-cli构建的vue项目,一个使用angular的项目,两个项目在其他浏览器一切正常,但是ie中会报Promise未定义的错误 解决办法: vue的项目: 1. npm insta ...
- [剑指Offer] 35.数组中的逆序对
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
- Docker实战系列一:初识Docker for Windows
windows下安装Docker官网教程Install Docker for Windows Docker配置官网教程Get started with Docker for Windows