bzoj 1901 线段树套平衡树+二分答案查询
我们就建一颗线段树,线段树的每一个节点都是一颗平衡树,对于每个询问来说,我们就二分答案,
查询每个二分到的mid在这个区间里的rank,然后就行了
/**************************************************************
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;
bt :array[..] of longint;
b_size, b_left, b_right :array[..] of longint;
b_key :array[..] of longint;
tot :longint; function min(a,b:longint):longint;
begin
if a>b then min:=b else min:=a;
end; function max(a,b:longint):longint;
begin
if a>b then max:=a else max:=b;
end; procedure rotate_right(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_right[t]]+b_size[b_left[t]]+;
t:=k;
end; procedure rotate_left(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_right[t]]+b_size[b_left[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
rotate_right(b_left[t]) else
if b_size[b_right[b_left[t]]]>b_size[b_right[t]] then
begin
rotate_left(b_left[t]);
rotate_right(t);
end else exit;
end else
begin
if b_size[b_right[b_right[t]]]>b_size[b_left[t]] then
rotate_left(b_right[t]) else
if b_size[b_left[b_right[t]]]>b_size[b_left[t]] then
begin
rotate_right(b_right[t]);
rotate_left(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_right[t],v) else
insert(b_left[t],v);
maintain(t,v>=b_key[t]);
end;
end; function delete(var t:longint; v:longint):longint;
begin
dec(b_size[t]);
if (b_key[t]=v)
or (b_right[t]=) and (v>b_key[t])
or (b_left[t]=) and (v<b_key[t]) then
begin
delete:=b_key[t];
if (b_left[t]=) or (b_right[t]=) then
t:=b_right[t]+b_left[t] else
b_key[t]:=delete(b_left[t],v+);
end else
if v<b_key[t] then delete:=delete(b_left[t],v) else
delete:=delete(b_right[t],v);
end; function rank(var t:longint; v:longint):longint;
begin
if t= then exit();
if v<=b_key[t] then rank:=rank(b_left[t],v) else
rank:=rank(b_right[t],v)+b_size[b_left[t]]+;
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,a[i]);
if l=r then exit;
mid:=(l+r) div ;
build(x*,l,mid); build(x*+,mid+,r);
end; procedure change(x,y,z:longint);
var
mid :longint;
begin
mid:=delete(t[x].root,a[y]);
insert(t[x].root,z);
if t[x].left=t[x].right then exit;
with t[x] do mid:=(left+right) div ;
if y>mid then change(x*+,y,z) else change(x*,y,z);
end; function ask(x,l,r,k:longint):longint;
var
mid :longint;
begin
ask:=;
if (t[x].left=l) and (t[x].right=r) then
begin
ask:=rank(t[x].root,k);
exit;
end;
with t[x] do mid:=(left+right) div ;
if mid<l then ask:=ask(x*+,l,r,k) else
if mid>=r then ask:=ask(x*,l,r,k) else
ask:=ask(x*,l,mid,k)+ask(x*+,mid+,r,k);
end; function succ(var t:longint;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; function pred(var t:longint;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 ask_succ(x,l,r,y:longint):longint;
var
mid :longint;
begin
if (t[x].left=l) and (t[x].right=r) then
begin
ask_succ:=succ(t[x].root,y);
if ask_succ=- then ask_succ:=maxlongint;
exit;
end;
with t[x] do mid:=(left+right) div ;
if l>mid then ask_succ:=ask_succ(x*+,l,r,y) else
if r<=mid then ask_succ:=ask_succ(x*,l,r,y) else
ask_succ:=min(ask_succ(x*,l,mid,y),ask_succ(x*+,mid+,r,y));
end; function ask_pred(x,l,r,y:longint):longint;
var
mid :longint;
begin
if (t[x].left=l) and (t[x].right=r) then
begin
ask_pred:=pred(t[x].root,y);
exit;
end;
with t[x] do mid:=(left+right) div ;
if l>mid then ask_pred:=ask_pred(x*+,l,r,y) else
if r<=mid then ask_pred:=ask_pred(x*,l,r,y) else
ask_pred:=max(ask_pred(x*,l,mid,y),ask_pred(x*+,mid+,r,y));
end; procedure query(x,y,k:longint);
var
l, r, mid :longint;
ans :longint;
xx :longint;
begin
l:=; r:=;
while l<=r do
begin
mid:=(l+r) div ;
xx:=ask(,x,y,mid);
if xx>=k- then
begin
ans:=mid;
r:=mid-;
end else l:=mid+;
end;
if ask(,x,y,ans)<>k- then
xx:=ask_pred(,x,y,ans-) else
xx:=ask_succ(,x,y,ans);
writeln(xx);
end; procedure init;
var
i :longint;
begin
read(n,m);
for i:= to n do read(a[i]);
readln;
build(,,n);
end; procedure main;
var
i :longint;
ch :char;
l, r, x :longint; begin
for i:= to m do
begin
read(ch);
if ch='Q' then
begin
readln(l,r,x);
query(l,r,x);
end else
begin
readln(l,x);
change(,l,x);
a[l]:=x;
end;
end;
end; begin
init;
main;
end.
bzoj 1901 线段树套平衡树+二分答案查询的更多相关文章
- bzoj 2120 线段树套平衡树
先吐下槽,改了快一个小时,最后发现是SBT的delete写错了,顿时就有想死的心..... 首先对于这道题,我们应该先做一下他的小问题,bzoj1878,虽然和这道题几乎一点关系没有, 但是能给我们一 ...
- 【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1146 第一种做法(时间太感人): 第二种做法(rank5,好开心) ================ ...
- 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 ...
- [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...
- bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description ...
- 浅谈树套树(线段树套平衡树)&学习笔记
0XFF 前言 *如果本文有不好的地方,请在下方评论区提出,Qiuly感激不尽! 0X1F 这个东西有啥用? 树套树------线段树套平衡树,可以用于解决待修改区间\(K\)大的问题,当然也可以用 ...
- BZOJ3196二逼平衡树——线段树套平衡树(treap)
此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...
- P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)
P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...
随机推荐
- vue2.0 $emit $on组件通信
在vue1.0中父子组件通信使用$dispatch 和 $broadcast,但是在vue2.0中$dispatch 和 $broadcast 已经被弃用. 因为基于组件树结构的事件流方式实在是让人难 ...
- 「日常训练」「小专题·USACO」 Barn Repair(1-4)
题意 之后补. 分析 这题同样也很精巧.我们不妨思考一下,如果只允许用一块木板,那么要购买多少距离?是整个的距离吗?不是,是从第一个到最后一个(哈哈哈哈哈哈哈).但是,不包括第一个的"左边& ...
- Linux下的调试工具
Linux下的调试工具 随着XP的流行,人们越来越注重软件的前期设计.后期的实现,以及贯穿于其中的测试工作,经过这个过程出来的自然是高质量的软件.甚至有人声称XP会淘汰调试器!这当然是有一定道理的,然 ...
- Qt Qwdget 汽车仪表知识点拆解2 图像放大
先贴上效果图,注意,没有写逻辑,都是乱动的 这里讲下 这个小汽车的进入过程,其实这个说白了就没有技术含量了,本来应该趁着这个机会学习一下Qt的动画机制,不过随机一想,这个自己写也累不到那里去 下面说下 ...
- 第七篇Python基本数据类型之数字&字符串&布尔值
数字 写在最前,必须要会的:int() 整型 Python3里无论数字多长都用int表示,Python2里有int和Long表示,Long表示长整型 有关数字的常用方法,方法调用后面都必须带括号() ...
- 10-Mysql数据库----数据的增删改
本节重点: 插入数据 INSERT 更新数据 UPDATE 删除数据 DELETE 再来回顾一下之前我们练过的一些操作,相信大家都对插入数据.更新数据.删除数据有了全面的认识.那么在mysql中其实最 ...
- POJ 2761 Feed the dogs(平衡树or划分树or主席树)
Description Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to feed the dogs ...
- lintcode-103-带环链表 II
带环链表 II 给定一个链表,如果链表中存在环,则返回到链表中环的起始节点的值,如果没有环,返回null. 样例 给出 -21->10->4->5, tail connects to ...
- 牛客网(string::find()函数回忆一下)
链接:https://www.nowcoder.com/acm/contest/109/B来源:牛客网 给出两个串s和x 定义s中的某一位i为好的位置,当且仅当存在s的子序列 满足y=x且存在j使得i ...
- PAT 1020 月饼
https://pintia.cn/problem-sets/994805260223102976/problems/994805301562163200 月饼是中国人在中秋佳节时吃的一种传统食品,不 ...