3196: Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
[Submit][Status][Discuss]

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)

Input

第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

Output

对于操作1,2,4,5各输出一行,表示查询结果

Sample Input

9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5

Sample Output

2
4
3
4
9

HINT

1.n和m的数据范围:n,m<=50000

2.序列中每个数的数据范围:[0,1e8]

3.虽然原题没有,但事实上5操作的k可能为负数
 
线段树套平衡树
#include<cstdio>
#include<algorithm>
using namespace std;
#define M 3000001
#define N 50001 int id=;
int siz[M],cnt[M],key[M];
int fa[M],ch[M][];
struct TREE
{
int root,l,r;
}tr[N<<];
int data[N];
void Splay_up(int k)
{
siz[k]=siz[ch[k][]]+siz[ch[k][]]+cnt[k];
}
void rotate(int x,int &goal)
{
int y=fa[x],z=fa[y];
int l=ch[y][]==x,r=l^;
if(y==goal) goal=x;
else ch[z][ch[z][]==y]=x;
ch[y][l]=ch[x][r]; ch[x][r]=y;
fa[x]=z; fa[y]=x; fa[ch[y][l]]=y;
Splay_up(y);
}
void splay(int x,int &goal)
{
int y,z;
while(x!=goal)
{
y=fa[x]; z=fa[y];
if(y!=goal)
{
if(ch[z][]==y ^ ch[y][]==x) rotate(x,goal);
else rotate(y,goal);
}
rotate(x,goal);
Splay_up(x);
}
}
void Splay_insert(int &rt,int w)
{
if(!rt)
{
rt=++id;
siz[rt]=cnt[rt]=;
key[rt]=w;
return;
}
if(key[rt]==w) cnt[rt]++;
else if(w<key[rt]) Splay_insert(ch[rt][],w),fa[ch[rt][]]=rt;
else Splay_insert(ch[rt][],w),fa[ch[rt][]]=rt;
Splay_up(rt);
}
int Splay_getpre(int rt,int x)
{
int now=rt,ret;
while(now)
{
if(key[now]>=x) now=ch[now][];
else ret=now,now=ch[now][];
}
return ret;
}
int Splay_getsuc(int rt,int x)
{
int now=rt,ret;
while(now)
{
if(key[now]<=x) now=ch[now][];
else ret=now,now=ch[now][];
}
return ret;
}
int Splay_number(int now,int w)
{
while()
{
if(key[now]==w) return now;
if(w<key[now]) now=ch[now][];
else now=ch[now][];
}
}
void del(int & rt,int w)
{
int num=Splay_number(rt,w);
splay(num,rt);
if(cnt[num]>) cnt[num]--, siz[num]--;
else
{
int pre=Splay_getpre(rt,w);
splay(pre,rt);
ch[pre][]=ch[num][];
fa[ch[pre][]]=pre;
Splay_up(pre);
}
}
void add_dummy(int rt,int w,int d)
{
ch[rt][d]=++id; siz[rt]++;
fa[id]=rt; siz[id]=cnt[id]=; key[id]=w;
} void build(int k,int l,int r)
{
tr[k].l=l; tr[k].r=r;
if(l==r) return;
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
}
void Segment_insert(int k,int pos,int w)
{
Splay_insert(tr[k].root,w);
if(tr[k].l==tr[k].r) return;
int mid=tr[k].l+tr[k].r>>;
if(pos<=mid) Segment_insert(k<<,pos,w);
else Segment_insert(k<<|,pos,w);
}
void dummy(int k)
{
int pre=Splay_getsuc(tr[k].root,-),suc=Splay_getpre(tr[k].root,1e8);
splay(pre,tr[k].root);
add_dummy(pre,-1e8-,);
splay(suc,tr[k].root);
add_dummy(suc,1e8+,);
if(tr[k].l==tr[k].r) return;
dummy(k<<); dummy(k<<|);
}
int order(int k,int opl,int opr,int w)
{
if(tr[k].l>=opl && tr[k].r<=opr)
{
int pre=Splay_getpre(tr[k].root,w);
splay(pre,tr[k].root);
return siz[ch[pre][]]+cnt[pre]-;
}
int mid=tr[k].l+tr[k].r>>,tmp=;
if(opl<=mid) tmp+=order(k<<,opl,opr,w);
if(opr>mid) tmp+=order(k<<|,opl,opr,w);
return tmp;
}
int Segment_number(int l,int r,int w)
{
int ll=,rr=1e8,mid,tmp,ans;
while(ll<=rr)
{
mid=ll+rr>>;
tmp=order(,l,r,mid);
if(tmp<w) ans=mid,ll=mid+;
else rr=mid-;
}
return ans;
}
void modify(int k,int pos,int before,int now)
{
del(tr[k].root,before);
Splay_insert(tr[k].root,now);
if(tr[k].l==tr[k].r)
{
data[tr[k].l]=now;
return;
}
int mid=tr[k].l+tr[k].r>>;
if(pos<=mid) modify(k<<,pos,before,now);
else modify(k<<|,pos,before,now);
}
int Segment_getpre(int k,int l,int r,int w)
{
if(tr[k].l>=l && tr[k].r<=r) return key[Splay_getpre(tr[k].root,w)];
int mid=tr[k].l+tr[k].r>>,tmp=-1e8-;
if(l<=mid) tmp=max(tmp,Segment_getpre(k<<,l,r,w));
if(r>mid) tmp=max(tmp,Segment_getpre(k<<|,l,r,w));
return tmp;
}
int Segment_getsuc(int k,int l,int r,int w)
{
if(tr[k].l>=l && tr[k].r<=r) return key[Splay_getsuc(tr[k].root,w)];
int mid=tr[k].l+tr[k].r>>,tmp=1e8+;
if(l<=mid) tmp=min(tmp,Segment_getsuc(k<<,l,r,w));
if(r>mid) tmp=min(tmp,Segment_getsuc(k<<|,l,r,w));
return tmp;
} int main()
{
freopen("psh.in","r",stdin);
freopen("psh.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
build(,,n);
for(int i=;i<=n;i++)
{
scanf("%d",&data[i]);
Segment_insert(,i,data[i]);
}
dummy();
int opt,l,r,k;
while(m--)
{
scanf("%d",&opt);
if(opt==)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",order(,l,r,k)+);
}
else if(opt==)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",Segment_number(l,r,k));
}
else if(opt==)
{
scanf("%d%d",&l,&k);
modify(,l,data[l],k);
}
else if(opt==)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",Segment_getpre(,l,r,k));
}
else
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",Segment_getsuc(,l,r,k));
}
}
}

bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)的更多相关文章

  1. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1807  Solved: 772[Submit][Stat ...

  2. BZOJ 3196: Tyvj 1730 二逼平衡树( 树套树 )

    这道题做法应该很多吧.... 我用了线段树套treap.... -------------------------------------------------------------------- ...

  3. BZOJ 3196 Tyvj 1730 二逼平衡树 树套树 线段树 treap

    http://www.lydsy.com/JudgeOnline/problem.php?id=3196 http://hzwer.com/2734.html 线段树套treap,似乎splay也可以 ...

  4. BZOJ 3196 Tyvj 1730 二逼平衡树:线段树套splay

    传送门 题意 给你一个长度为 $ n $ 有序数列 $ a $ ,进行 $ m $ 次操作,操作有如下几种: 查询 $ k $ 在区间 $ [l,r] $ 内的排名 查询区间 $ [l,r] $ 内排 ...

  5. BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)

    题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...

  6. bzoj 3196 Tyvj 1730 二逼平衡树【线段树 套 splay】

    四舍五入就是个暴力. 对于线段树的每个区间都开一棵按权值排序的splay 对于第二个操作,二分一下,每次查询mid的排名,复杂度 $ O(nlog(n)^{3}) $ 其余的操作都是$ O(nlog( ...

  7. bzoj 3196: Tyvj 1730 二逼平衡树

    #include<cstdio> #include<ctime> #include<cstdlib> #include<iostream> #defin ...

  8. BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树

    [题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...

  9. BZOJ3196二逼平衡树——线段树套平衡树(treap)

    此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...

随机推荐

  1. [C++] Class (part 2)

    Members that are const or reference must be initialized. Similary, members that are of a class type ...

  2. 《剑指Offer》题五十一~题六十

    五十一.数组中的逆序对 题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数.例如,在数组{7, 5, 6, 4}中,一共存 ...

  3. Gym - 100851F Froggy Ford kruskal

    题目链接: http://acm.hust.edu.cn/vjudge/problem/307216 Froggy Ford Time Limit: 3000MS 题意 青蛙过河,河中有若干个石头,现 ...

  4. DAY7敏捷冲刺

    站立式会议 工作安排 (1)服务器配置 服务器端项目结构调整 (2)数据库配置 单词学习记录+用户信息 (3)客户端 客户端项目结构调整,代码功能分离 燃尽图 燃尽图有误,已重新修改,先贴卡片的界面, ...

  5. Java容器之Collections

    Collections 类来源于 java.util.Collections,从 java.lang.object继承. 此类完全由在 collection 上进行操作或返回 collection 的 ...

  6. sublime Remote_encoding cp1252

    "remote_encoding": "cp1252",才能连接远程ftp

  7. URL中编码问题

    1.http协议传输统一iso-8859-1传输 jsp中用request.getparameter("keword");得到的是iso-8859-1翻译过来的,要用 keywor ...

  8. Java-通过比较throw与throws来阐述抛出异常

    转自:http://www.cnblogs.com/Miracle-Maker/p/6239346.html 浅谈Java异常 以前虽然知道一些异常的处理,也用过一些,但是对throw和throws区 ...

  9. 使用mac电脑,对Github客户端的简单操作1----开源项目

    工作之余自己也会一写一些小的程序项目,由于一直没时间“折腾”开源,之前写博客都是直接粘代码片段,今天看别人写技术博客大都会放出项目Github地址,突然感觉自己有点点out and low,作为一个励 ...

  10. 【bzoj5085】最大 二分+暴力

    题目描述 给你一个n×m的矩形,要你找一个子矩形,价值为左上角左下角右上角右下角这四个数的最小值,要你最大化矩形的价值. 输入 第一行两个数n,m,接下来n行每行m个数,用来描述矩形 n, m ≤ 1 ...