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可能为负数
写了不很久,但是交上去一直都是TLE,发现splay被卡了。最后采用随机提根法,卡过去了。
一道树套树的裸题(很明显线段树套平衡树)。
 #include<iostream>
#include<queue>
#include<cstdio>
#include<cstdlib>
using namespace std; #define inf (1<<29)
#define lim (100000000)
#define maxn (50010)
#define maxm (3000010)
int n,m,root[maxn*],seq[maxn];
struct SPLAY
{
queue <int> team; int cnt,ch[maxm][],fa[maxm],key[maxm],t[maxm],size[maxm]; inline int newnode()
{
int ret;
if (!team.empty()) ret = team.front(),team.pop();
else ret = ++cnt;
fa[ret] = ch[ret][] = ch[ret][] = t[ret] = ;
return ret;
} inline void updata(int now) { size[now] = size[ch[now][]] + size[ch[now][]] + t[now]; } inline void rotate(int x)
{
int y = fa[x],z = fa[y],l = ch[y][] == x,r = l^;
if (z) ch[z][ch[z][] == y] = x; fa[x] = z;
if (ch[x][r]) fa[ch[x][r]] = y; ch[y][l] = ch[x][r];
ch[x][r] = y; fa[y] = x;
updata(y); updata(x);
} inline void splay(int x,int rt)
{
while (fa[x])
{
int y = fa[x],z = fa[y];
if (z)
{
if ((ch[y][] == x)^(ch[z][] == y)) rotate(x);
else rotate(y);
}
rotate(x);
}
root[rt] = x;
} inline void init(int rt)
{
int p = newnode(),q = newnode();
root[rt] = p; ch[p][] = q; fa[q] = p;
t[p]++; key[p] = -inf; t[q]++; key[q] = inf;
updata(q); updata(p);
} inline int find(int w,int rt,int sign)
{
int now = root[rt],ret;
while (now)
{
if (!sign)
{
if (key[now] == w) return now;
now = ch[now][key[now]<w];
}
else if (sign == )
{
if (key[now] < w) ret = now,now = ch[now][];
else now = ch[now][];
}
else if (sign == )
{
if (key[now] > w) ret = now,now = ch[now][];
else now = ch[now][];
}
else
{
if (key[now] >= w) ret = now,now = ch[now][];
else now = ch[now][];
}
}
return ret;
} inline void erase(int w,int rt)
{
int p = find(w,rt,);
while (ch[p][]||ch[p][])
{
if (ch[p][])
{
if (root[rt] == p) root[rt] = ch[p][];
rotate(ch[p][]);
}
else
{
if (root[rt] == p) root[rt] = ch[p][];
rotate(ch[p][]);
}
}
int now = p;
if (!--t[now]) ch[fa[now]][key[fa[now]] < key[now]] = ,team.push(now);
else updata(now);
while (now = fa[now],now) updata(now);
} inline void insert(int w,int rt)
{
int now = root[rt],pre = ;
while (now)
{
if (key[now] == w) { ++t[now]; break; }
pre = now; now = ch[now][w > key[now]];
}
if (!now)
now = newnode(),fa[now] = pre,ch[pre][w > key[pre]] = now,key[now] = w,++t[now];
for (pre = now;pre;pre = fa[pre]) updata(pre);
if (w & ) splay(now,rt);
} inline int rank(int w,int rt)
{
int p = find(w,rt,); splay(p,rt);
return size[ch[p][]];
}
}tree; inline void build(int l,int r,int now)
{
tree.init(now);
for (int i = l;i <= r;++i) tree.insert(seq[i],now);
if (l == r) return;
int mid = (l + r) >> ;
build(l,mid,now<<); build(mid+,r,now<<|);
} inline int rank(int l,int r,int ql,int qr,int now,int w)
{
if (ql <= l && qr >= r) return tree.rank(w,now)-;
int mid = (l + r) >> ;
if (qr <= mid) return rank(l,mid,ql,qr,now<<,w);
else if (ql > mid) return rank(mid+,r,ql,qr,now<<|,w);
else return rank(l,mid,ql,mid,now<<,w)+rank(mid+,r,ql,qr,now<<|,w);
} inline void change(int l,int r,int now,int pos,int w)
{
tree.erase(seq[pos],now); tree.insert(w,now);
if (l == r) return;
int mid = (l + r) >> ;
if (pos <= mid) change(l,mid,now<<,pos,w);
else change(mid+,r,now<<|,pos,w);
} inline int ask(int l,int r,int ql,int qr,int now,int w,int sign)
{
if (ql <= l && qr >= r) return tree.key[tree.find(w,now,sign)];
int mid = (l + r)>>;
if (qr <= mid) return ask(l,mid,ql,qr,now<<,w,sign);
else if (ql > mid) return ask(mid+,r,ql,qr,now<<|,w,sign);
else
{
if (sign == ) return max(ask(l,mid,ql,mid,now<<,w,sign),ask(mid+,r,mid+,qr,now<<|,w,sign));
else return min(ask(l,mid,ql,mid,now<<,w,sign),ask(mid+,r,mid+,qr,now<<|,w,sign));
}
} int main()
{
freopen("3196.in","r",stdin);
freopen("3196.out","w",stdout);
scanf("%d %d",&n,&m);
for (int i = ;i <= n;++i) scanf("%d",seq+i);
build(,n,);
while (m--)
{
int opt; scanf("%d",&opt);
if (opt == )
{
int l,r,w; scanf("%d %d %d",&l,&r,&w);
printf("%d\n",rank(,n,l,r,,w)+);
}
else if (opt == )
{
int l,r,k; scanf("%d %d %d",&l,&r,&k);
int ll = ,rr = lim;
while (ll <= rr)
{
int mid = (ll + rr) >> ;
if (rank(,n,l,r,,mid)+>k) rr = mid - ;
else ll = mid + ;
}
printf("%d\n",rr);
}
else if (opt == )
{
int pos,w; scanf("%d %d",&pos,&w);
change(,n,,pos,w); seq[pos] = w;
}
else
{
int l,r,w; scanf("%d %d %d",&l,&r,&w);
printf("%d\n",ask(,n,l,r,,w,opt-));
}
}
fclose(stdin); fclose(stdout);
return ;
}

BZOJ 3196 二逼平衡树的更多相关文章

  1. bzoj 3196二逼平衡树 线段树套平衡树

    比较裸的树套树,对于区间K值bz上有一道裸题,详见题解http://www.cnblogs.com/BLADEVIL/p/3455336.html(其实题解也不是很详细) //By BLADEVIL ...

  2. BZOJ 3196 二逼平衡树 ——树套树

    [题目分析] 全靠运气,卡空间. xjb试几次就过了. [代码] #include <cmath> #include <cstdio> #include <cstring ...

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

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

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

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

  5. bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...

  6. bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

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

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

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

  8. 【BZOJ 3196】二逼平衡树 线段树套splay 模板题

    我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...

  9. 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)

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

随机推荐

  1. PullToRefreshListView调用onRefreshComplete方法 无法取消刷新的bug

    我们在使用框架:   PullToRefreshListView 实现下拉或者上拉加载时候,可能在上拉 完成时候,调用onRefreshComplete方法去 停止 刷新操作,但是,可能无效,测试产生 ...

  2. Android开发ImageView控件缩放图片

    首先还是最基础的ImageView控件如何显示图片: <ImageView                Android:id="@+id/imgView"          ...

  3. 标记偏置 隐马尔科夫 最大熵马尔科夫 HMM MEMM

    隐马尔科夫模型(HMM): 图1. 隐马尔科夫模型 隐马尔科夫模型的缺点: 1.HMM仅仅依赖于每个状态和它相应的观察对象: 序列标注问题不仅和单个词相关,并且和观察序列的长度,单词的上下文,等等相关 ...

  4. etrace 跟踪程序函数动态执行流程

    https://github.com/elcritch/etrace 窗口1: 监控窗口,执行监控程序,显示监控结果 [root@monitor example]# pwd /root/etrace- ...

  5. Optimized Pagination using MySQL---reference

    Dealing with large data sets makes it necessary to pick out only the newest or the hottest elements ...

  6. 9.28noip模拟试题

    1.栅栏迷宫 田野上搭建了一个黄金大神专用的栅栏围成的迷宫.幸运的是,在迷宫的边界上留出了两段栅栏作为迷宫的出口.更幸运的是,所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意一点找到一条走出迷宫 ...

  7. SpringMVC4+thymeleaf3的一个简单实例(篇二:springMVC与thymeleaf的整合)

    延续前篇内容. 开始之前,我们首先要准备以下12个jar文件:spring-aop-4.3.3.RELEASE.jarspring-beans-4.3.3.RELEASE.jarspring-cont ...

  8. FlightGear 视角控制

    Flightgear提供了非常灵活的模块化功能 这里就简要记录一下视角切换功能 首先,需要了解一下Flightgear中的property tree的主要内容,这里暂略. http://wiki.fl ...

  9. gvim 常用命令

    插入: insert 强退: :q! 退出: :q 保存: :w 保存退出::wq 复制: yy(单行)   多行:8yy 删除: dd(单行)   多行:8dd 或者 :4,8d 执行脚本: :! ...

  10. 调用数据库过程函数mysql

    Connection conn=JdbcUtil.getConnection();//JdbcUtil是我写的获取connection的工具类 CallableStatement cast=conn. ...