地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3196

题目:

3196: Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 4320  Solved: 1662
[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可能为负数
 
思路:
  第一次写树套树,以前一直觉得树套树是很可怕的东西,写了后发现思想很简单
  就是。。。。代码好长!debug麻烦!
  写了两小时,debug三小时。。
  不过1A了,美滋滋!
  代码跑了快九秒,好气哦,一定是姿势不对
 /**************************************************************
Problem: 3196
User: weeping
Language: C++
Result: Accepted
Time:8668 ms
Memory:83520 kb
****************************************************************/ #include <bits/stdc++.h> using namespace std; #define lc ch[x][0]
#define rc ch[x][1]
#define pr fa[x] inline int read()
{
int a=,f=; char c=getchar();
while (c<''||c>'') {if (c=='-') f=-; c=getchar();}
while (c>=''&&c<='') {a=a*+c-''; c=getchar();}
return a*f;
} const int N = 5e4+;
const int M = 3e6; int n, m, ans, val[N];
int tot, rt[M], ch[M][], fa[M], key[M], sz[M], cnt[M]; inline int wh(int x) { return ch[pr][] == x;} inline void init(int x,int ls,int ky)
{
lc=rc=,sz[x]=cnt[x]=,key[x]=ky,pr=ls;
}
inline void push_up(int x)
{
sz[x]=sz[lc]+sz[rc]+cnt[x];
}
void rotate(int x)
{
int f = fa[x], gf = fa[f], t1 = wh(x);
if( gf ) ch[gf][wh(f)] = x;
fa[x] = gf, ch[f][t1] = ch[x][^t1], fa[ch[f][t1]] = f;
ch[x][t1^] = f, fa[f] = x;
push_up( f ), push_up( x );
}
void splay(int o,int x,int tar)
{
for(;pr!=tar;rotate(x))
if(fa[pr]!=tar) rotate(wh(x)==wh(pr)?pr:x);
if(!tar) rt[o]=x;
}
//void debug(int x)
//{
// if(!x) return;
// if(lc) debug(lc);
// for(int i=1;i<=cnt[x];i++)
// printf("%d ",key[x]);
// if(rc) debug(rc);
//}
void insert(int o,int ky)
{
int x=rt[o],ls=rt[o];
while(x)
{
if(key[x]==ky)
{
sz[x]++,cnt[x]++,splay(o,x,);return;
}
ls=x,x=ch[x][ky>key[x]];
}
init(++tot,ls,ky);
if(!rt[o]) { rt[o]=tot; return ;}
x=ls, ch[x][ky>key[x]]=tot;
splay(o,tot,);
}
int find(int o,int ky)
{
int x=rt[o];
//debug(rt[o]);printf("\n");
while(x)
{
if(key[x]==ky) break;
x=ch[x][ky>key[x]];
}
if(x) splay(o,x,);
else x=-;
return x;
}
void merge(int o,int x,int y)
{
if(!x){rt[o]=y;return;}
if(!y) {rt[o]=x;return;}
while(rc) x=rc;
splay(o,x,);
rc=y,fa[y]=x;
push_up(x);
}
void del(int o,int ky)
{
if(!rt[o]) return;
int x=find(o,ky);
if(cnt[x]>) {cnt[x]--,sz[x]--;return;}
int tl=lc,tr=rc;
fa[tl]=fa[tr]=cnt[x]=sz[x]=lc=rc=;
if(sz[x]==) {rt[o]=;return;}
merge(o,tl,tr);
}
void getpre(int x,int ky)
{
if(!x)return;
if(key[x]<ky) ans=max(ans,key[x]),getpre(rc,ky);
else getpre(lc,ky);
}
void getnext(int x,int ky)
{
if(!x) return;
if(key[x]>ky) ans=min(ans,key[x]),getnext(lc,ky);
else getnext(rc,ky);
}
int getsz(int o,int ky)
{
int x=rt[o],ret=;
while(x)
{
if(key[x]==ky) return ret+sz[lc];
if(key[x]<ky) ret+=sz[lc]+cnt[x],x=rc;
else x=lc;
}
return ret;
} void update(int o,int l,int r,int pos,int x,int op=)
{
if(op) del(o,val[pos]);
insert(o,x);
//debug(rt[o]);printf("\n");
if(l==r) return ;
int mid=l+r>>;
if(pos<=mid) update(o<<,l,mid,pos,x,op);
else update(o<<|,mid+,r,pos,x,op);
}
int get_rank(int o,int l,int r,int nl,int nr,int ky)
{
//debug(rt[o]);printf("\n");
if(nl==l&&r==nr) return getsz(o,ky);
int mid=l+r>>;
if(nr<=mid) return get_rank(o<<,l,mid,nl,nr,ky);
else if(nl>mid) return get_rank(o<<|,mid+,r,nl,nr,ky);
return get_rank(o<<,l,mid,nl,mid,ky)+get_rank(o<<|,mid+,r,mid+,nr,ky);
}
void get_pre(int o,int l,int r,int nl,int nr,int ky)
{
if(nl==l&&r==nr) return getpre(rt[o],ky);
int mid=l+r>>;
if(nr<=mid) return get_pre(o<<,l,mid,nl,nr,ky);
else if(nl>mid) return get_pre(o<<|,mid+,r,nl,nr,ky);
get_pre(o<<,l,mid,nl,mid,ky),get_pre(o<<|,mid+,r,mid+,nr,ky);
}
void get_next(int o,int l,int r,int nl,int nr,int ky)
{
//debug(rt[o]);printf("\n");
if(nl==l&&r==nr) return getnext(rt[o],ky);
int mid=l+r>>;
if(nr<=mid) return get_next(o<<,l,mid,nl,nr,ky);
else if(nl>mid) return get_next(o<<|,mid+,r,nl,nr,ky);
get_next(o<<,l,mid,nl,mid,ky),get_next(o<<|,mid+,r,mid+,nr,ky);
}
int get_kth(int nl,int nr,int k)
{
int l=,r=1e8+,ans=;
while(l<=r)
{
int mid=l+r>>;
if(get_rank(,,n,nl,nr,mid)+<=k) l=mid+,ans=mid;
else r=mid-;
}
return ans;
}
int main(void)
{
n=read(),m=read();
for(int i=;i<=n;i++)
val[i]=read(),update(,,n,i,val[i]);
int op,l,r,x;
while(m--)
{
op=read(),l=read(),r=read();
if(op==)
{update(,,n,l,r,);val[l]=r;continue;}
x=read();
if(op==)
ans=get_rank(,,n,l,r,x)+;
else if(op==)
ans=get_kth(l,r,x);
else if(op==)
ans=-0x3f3f3f3f,get_pre(,,n,l,r,x);
else
ans=0x3f3f3f3f,get_next(,,n,l,r,x);
printf("%d\n",ans);
}
}

bzoj3196: 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 二逼平衡树 (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ...

  3. [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树

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

  4. 【分块】bzoj3196 Tyvj 1730 二逼平衡树

    分块 或 树套树. 在每个块中维护一个有序表,查询时各种二分,全都是分块的经典操作,就不详细说了. 块的大小定为sqrt(n*log2(n))比较快. #include<cstdio> # ...

  5. 【线段树套平衡树】【pb_ds】bzoj3196 Tyvj 1730 二逼平衡树

    线段树套pb_ds里的平衡树,在洛谷OJ上测试,后三个测试点TLE #include<cstdio> #include<algorithm> #include<ext/p ...

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

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

  7. BZOJ3196: Tyvj 1730 二逼平衡树

    传送门 主席树的常数蜜汁优越,在BZOJ上跑了rnk1. 做法很简单,主席树套BIT. 1-3做法很简单,第四个和第五个做法转换成前两个就行了. //BZOJ 3196 //by Cydiater / ...

  8. [bzoj3196][Tyvj 1730][二逼平衡树] (线段树套treap)

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

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

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

随机推荐

  1. 本地项目通过github客户端上传到github网站上

    一.github客户端上传步骤 一.github客户端上传步骤1.百度搜索关键字: GitHub 离线安装包 ==> Github_3.3.4.0版本链接:https://pan.baidu.c ...

  2. C# IO流的操作(一)

    C# IO流的操作非常重要,我们读写文件都会使用到这个技术,这里先演示一个文件内容复制的例子,简要说明C#中的IO操作. namespace ConsoleApplication1 { class P ...

  3. [SQL] 命令远程恢复数据库

    sp_configure ; RECONFIGURE; GO sp_configure ; RECONFIGURE; GO EXEC master..xp_cmdshell 'net use \\70 ...

  4. 【转】JavaScript 事件顺序:冒泡和捕获

    补充说明:这篇文章通俗易懂地讲解了冒泡和捕获原理,原文来自 ppk 大侠的 quirksmode 站点.感谢网友 hh54188 的翻译. 事件的发生顺序 这个问题的起源非常简单,假设你在一个元素中又 ...

  5. js遍历json对象

    原生js遍历json对象 遍历json对象: 无规律: <script> var json = [ {dd:'SB',AA:'东东',re1:123}, {cccc:'dd',lk:'1q ...

  6. HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...

  7. codeforces 798B - Mike and strings

    感觉自己好咸鱼呀……B题写了这么久,虽然可以算作1A(忽略一次少include一个头文件的CE)…… 思想很简单,每次选定一个字符串作为目标字符串,然后把其他所有字符串都当做测试字符串,计算出总共需要 ...

  8. HTML的常用总结

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. android udev

    http://www.freesoftwaremagazine.com/articles/drivers_linux http://blog.csdn.net/jianchi88/article/de ...

  10. 学习计划 mysql 用户管理与权限

    最近在学习数据库的 主从复制 里面涉及到了关于用户及其管理权限的赋予,之前一直没有认真的学习这个. 现在想具体的学习一下. -- 为什么 数据库 要实现多用户管理? 举个最简单的例子,你需要和第三方做 ...