然而我还是在继续刷水题。。。

终于解开了区间第k大的心结。。。

比较裸的线段树套平衡树,比较不好想的是求区间第k大时需要二分一下答案,然后问题就转化为了第一个操作。复杂度nlog3n。跑的比较慢。。。

在查前驱后继的时候写错了。。。如果要直接赋值ans的话前驱是k[x]<=z,后继是k[x]<z,如果都写<的话需要取max和min。。。(不是第一次犯这种错了)

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lc x*2,l,mid
#define rc x*2+1,mid+1,r
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
#define inf 0x3f3f3f3f
using namespace std;
int n,m;
int root[*];
int size[*],k[*];
int ch[*][],fa[*];
int a[];
int cnt;
inline void push_up(int x)
{
size[x]=size[ch[x][]]+size[ch[x][]]+;
return ;
}
inline void rotate(int p)
{
int q=fa[p],y=fa[q],x=(ch[q][]==p);
ch[q][x]=ch[p][x^];fa[ch[q][x]]=q;
ch[p][x^]=q;fa[q]=p;fa[p]=y;
if(y)
{
if(ls(y)==q)ch[y][]=p;
else ch[y][]=p;
}
push_up(q);push_up(p);
}
inline void splay(int now,int x)
{
for(int y;y=fa[x];rotate(x))
{
if(fa[y])
{
if((ls(y)==x&&ls(fa[y])==y)||(rs(y)==x&&rs(fa[y])==y))rotate(y);
else rotate(x);
}
}
root[now]=x;
}
inline void insert(int now,int x,int z)
{
size[x]++;
while(ch[x][k[x]<z])x=ch[x][k[x]<z],size[x]++;
ch[x][k[x]<z]=++cnt;fa[cnt]=x;size[cnt]=;k[cnt]=z;splay(now,cnt);
}
inline void build(int x,int l,int r)
{
root[x]=++cnt;k[cnt]=a[l];size[cnt]=;
for(int i=l+;i<=r;i++)insert(x,root[x],a[i]);
int mid=(l+r)>>;
if(l<r)build(lc),build(rc);
return ;
}
inline int fd(int x,int z)
{
int ans=;
while(x)
{
if(k[x]>z)
{
x=ch[x][];
}
else ans+=size[ch[x][]]+,x=ch[x][];
}
return ans;
}
inline int qur(int x,int l,int r,int ll,int rr,int kk)
{
if(ll<=l&&rr>=r)
{
return fd(root[x],kk);
}
int mid=(l+r)>>;
int ans=;
if(ll<=mid)ans+=qur(lc,ll,rr,kk);
if(rr>mid)ans+=qur(rc,ll,rr,kk);
return ans;
}
inline int find(int x,int z)
{
if(k[x]==z)return x;
while(ch[x][k[x]<z])
{
x=ch[x][k[x]<z];if(k[x]==z)return x;
}
return ;
}
inline void del(int now,int x)
{
splay(now,x);
if(!ch[x][])root[now]=ch[x][],fa[ch[x][]]=;
else if(!ch[x][])root[now]=ch[x][],fa[ch[x][]]=;
else
{
fa[ch[x][]]=;int tmp=ch[x][];
while(ch[tmp][])tmp=ch[tmp][];
splay(now,tmp);ch[tmp][]=ch[x][];fa[ch[x][]]=tmp;push_up(tmp);
}
}
inline void gai(int x,int l,int r,int pos,int z)
{
insert(x,root[x],z);
int x1=find(root[x],a[pos]);
del(x,x1);
if(l==r)return ;
int mid=(l+r)>>;
if(pos<=mid)gai(lc,pos,z);
else gai(rc,pos,z);
}
inline int pre(int x,int z)
{
int ans=-inf;
while(ch[x][k[x]<=z])
{
if(k[x]<=z)ans=k[x];
x=ch[x][k[x]<=z];
}if(k[x]<=z)ans=max(ans,k[x]);
return ans;
}
inline int suc(int x,int z)
{
int ans=inf;
while(ch[x][k[x]<z])
{
if(k[x]>=z)ans=k[x];
x=ch[x][k[x]<z];
}if(k[x]>=z)ans=min(ans,k[x]);
return ans;
}
inline int qur_pre(int x,int l,int r,int ll,int rr,int kk)
{
if(l>=ll&&r<=rr)
{
return pre(root[x],kk);
}
int ans=-inf;
int mid=(l+r)>>;
if(ll<=mid)ans=max(ans,qur_pre(lc,ll,rr,kk));
if(rr>mid)ans=max(ans,qur_pre(rc,ll,rr,kk));
return ans;
}
inline int qur_suc(int x,int l,int r,int ll,int rr,int kk)
{
if(l>=ll&&r<=rr)
{
return suc(root[x],kk);
}
int ans=inf;
int mid=(l+r)>>;
if(ll<=mid)ans=min(ans,qur_suc(lc,ll,rr,kk));
if(rr>mid)ans=min(ans,qur_suc(rc,ll,rr,kk));
return ans;
}
int mn,mx;
int main()
{
scanf("%d%d",&n,&m);mn=inf;mx=-inf;
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);mn=min(mn,a[i]);mx=max(mx,a[i]);
}
build(,,n);
for(int i=;i<=m;i++)
{
int t1;
scanf("%d",&t1);
int l,r,kk;
if(t1==)
{
scanf("%d%d%d",&l,&r,&kk);
printf("%d\n",qur(,,n,l,r,kk-)+);
}
else if(t1==)
{
scanf("%d%d%d",&l,&r,&kk);
int ha=mn;int ta=mx;
while(ha<=ta)
{
int mid=(ha+ta)>>;
if(qur(,,n,l,r,mid)<kk)ha=mid+;
else ta=mid-;
}
printf("%d\n",ha);
}
else if(t1==)
{
scanf("%d%d",&l,&kk);
gai(,,n,l,kk);a[l]=kk;
}
else if(t1==)
{
scanf("%d%d%d",&l,&r,&kk);
printf("%d\n",qur_pre(,,n,l,r,kk-));
}
else
{
scanf("%d%d%d",&l,&r,&kk);
printf("%d\n",qur_suc(,,n,l,r,kk+));
}
}
return ;
}

bzoj 3196 树套树模板的更多相关文章

  1. bzoj 1901: Zju2112 Dynamic Rankings(树套树)

    1901: Zju2112 Dynamic Rankings 经典的带改动求区间第k小值问题 树套树模板,我是用的线段树套splay实现的,并且用的数组模拟的,所以可能空间略大,bzoj过了,zoj过 ...

  2. 洛谷 P3380 bzoj3196 Tyvj1730 【模板】二逼平衡树(树套树)

    [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数值 查询k在 ...

  3. 洛谷P3380 【模板】二逼平衡树(树套树)(线段树+树状数组)

    P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...

  4. 洛谷 P3380 【模板】二逼平衡树(树套树)-线段树套splay

    P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...

  5. [BZOJ 3489] A simple rmq problem 【可持久化树套树】

    题目链接:BZOJ - 3489 题目分析 “因为是OJ上的题,就简单点好了.”——出题人 真的..好..简单... 首先,我们求出每个数的前一个与它相同的数的位置,即 prev[i] ,如果前面没有 ...

  6. P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)

    P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...

  7. 【Luogu】P3380树套树模板(线段树套Splay)

    题目链接 幸甚至哉,歌以咏志. 拿下了曾经是那么遥不可及的线段树,学会了曾经高不可攀的平衡树,弄懂了装B的时候才挂在嘴边的树套树. 每道模板都是链上的一颗珠子.把它们挨个串起来,就成为我成长的历程. ...

  8. ZJOI2013 K大数查询 和 LG3380【模板】二逼平衡树(树套树)

    K大数查询 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c:如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的 ...

  9. 「luogu3380」【模板】二逼平衡树(树套树)

    「luogu3380」[模板]二逼平衡树(树套树) 传送门 我写的树套树--线段树套平衡树. 线段树上的每一个节点都是一棵 \(\text{FHQ Treap}\) ,然后我们就可以根据平衡树的基本操 ...

  10. BZOJ 3110: [Zjoi2013]K大数查询 [树套树]

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[Submit][Sta ...

随机推荐

  1. win10显示此电脑

    http://jingyan.baidu.com/article/3aed632e00dfe17011809169.html

  2. 窗口 - dialog - 概述与基本使用

    什么是dialog 对话框是一种特殊的窗口,它在顶部有一个工具栏,在底部有一个按钮栏.默认情况下,对话框(dialog)只有一个显示在头部右侧的关闭工具. 用户可以配置对话框行为来显示其他工具(比如: ...

  3. Eclipse使用Maven构建web项目

    1.创建Maven项目: 点击“File”菜单,或者通过工具栏的“New”创建Project,如下图所示: 选择Maven->Maven Project,弹出向导对话框,如下图所示: 选中Cre ...

  4. 招聘高级.Net工程师

    找钢网创新开发部真诚地邀请程序猿\媛们加入,一起来吃大闸蟹午餐. 在创新开发部你可以见证一个产品从零开始到爆发到改变一个大宗商品的行业,在创新开发部你有机会接触到国际范,你还有机会接触到韩国的妹纸.欧 ...

  5. shell 脚本替换文件中某个字符串

    1.将当前目录下包含jack串的文件中,jack字符串替换为tom sed -i "s/jack/tom/g" `grep "jack" -rl ./` 2.将 ...

  6. Linux 信号详解三(sleep,raise)

    sleep()函数 .sleep()函数作用:让进程睡眠 .能被信号打断,然后处理信号函数以后,就不再睡眠,直接向下执行代码 .sleep函数的返回值是剩余秒数 //sleep 函数 #include ...

  7. 如果动态设置json对象的key

    项目中要求动态设置json的key属性,如果按照一般的json设置方法是不行的.假如你把一个key设置为一个变量的话,那么最后js解析出来的就是key为这个变量名而不是这个变量的值. 解决:通过使用 ...

  8. Java7并发编程实战(一) 守护线程的创建和运行

    Java里有一种特殊的线程叫做守护(Daemon)线程,这种线程的优先级很低,通常来说,当一个应用程序里面没有其他线程运行的时候,守护线程才运行,当线程是程序中唯一运行的线程时,守护线程执行结束后,J ...

  9. MVC5 + EF6 + Bootstrap3 (15) 应用ModelState和Data Annotation做服务器端数据验证

    Slark.NET-博客园 http://www.cnblogs.com/slark/p/mvc5-ef6-bs3-get-started-server-side-validation.html 系列 ...

  10. 如何用 Nodejs 分析一个简单页面

    本文目的 在浏览器地址栏中输入 localhost:3000,在页面显示 博客园首页 的 20 篇文章标题. 过程分析 首先需要端口的监听,这就需要引入 Node 中最重要的模块之一 express. ...