题目链接

平衡树系列最后一题

坑啊

10s时间限制跑了9764ms。。。还是要学一学bit套主席树啦。。。

经典的线段树套treap。。。至于第一发为什么要TLE(我不会告诉你treap插入的时候忘了旋转 WOC)

自认为treap写的挺好看的(欢迎来喷)

 #include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define rre(i,r,l) for(int i=(r);i>=(l);i--)
#define re(i,l,r) for(int i=(l);i<=(r);i++)
#define Clear(a,b) memset(a,b,sizeof(a))
#define inout(x) printf("%d",(x))
#define douin(x) scanf("%lf",&x)
#define strin(x) scanf("%s",(x))
#define LLin(x) scanf("%lld",&x)
#define op operator
#define CSC main
typedef unsigned long long ULL;
typedef const int cint;
typedef long long LL;
using namespace std;
cint inf=;
void inin(int &ret)
{
ret=;int f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=;ch=getchar();}
while(ch>=''&&ch<='')ret*=,ret+=ch-'',ch=getchar();
ret=f?-ret:ret;
}
int ch[][],c[],s[],rr[],w[],ed;
struct segtree
{
int l,r,root;
segtree(){root=;}
void maintain(int k){if(k)s[k]=c[k]+s[ch[k][]]+s[ch[k][]];}
void rotate(int &k,int d)
{
int p=ch[k][d^];
ch[k][d^]=ch[p][d];
ch[p][d]=k;s[p]=s[k];
maintain(k),k=p;
}
private:
void add(int &k,const int &x)
{
if(!k)
{
k=++ed,w[k]=x,rr[k]=rand();s[k]=c[k]=;ch[k][]=ch[k][]=;
return ;
}s[k]++;
if(x==w[k]){c[k]++;return ;}
int d=x>w[k];add(ch[k][d],x);
if(rr[ch[k][d]]<rr[k])rotate(k,d^);
}
bool del(int &k,const int &x)
{
if(!k)return ;
if(x==w[k])
{
if(c[k]>){c[k]--,s[k]--;return ;}
if(!ch[k][]){k=ch[k][];return ;}
if(!ch[k][]){k=ch[k][];return ;}
if(rr[ch[k][]]<rr[ch[k][]])rotate(k,);
else rotate(k,);
return del(k,x);
}
int d=x>w[k];
if(del(ch[k][d],x))
{
s[k]--;
return ;
}
else return ;
}
int findrank(int k,const int &x)
{
if(!k)return ;
int pp=(ch[k][]?s[ch[k][]]:);
if(x==w[k])return pp;
if(x>w[k])return pp+c[k]+findrank(ch[k][],x);
return findrank(ch[k][],x);
}
int findwei(int k,const int &x)
{
if(!k)return ;
int pp=(ch[k][]?s[ch[k][]]:);
if(x<=pp)return findwei(ch[k][],x);
if(x>pp+c[k])return findwei(ch[k][],x-pp-c[k]);
return w[k]; }
void findqian(int k,const int &x,int &ans)
{
if(!k)return ;
if(x>w[k])ans=w[k],findqian(ch[k][],x,ans);
else findqian(ch[k][],x,ans);
}
void findhou(int k,const int &x,int &ans)
{
if(!k)return ;
if(x<w[k])ans=w[k],findhou(ch[k][],x,ans);
else findhou(ch[k][],x,ans);
}
public:
void add(int x){add(root,x);}
void del(int x){del(root,x);}
int findrank(int x){return findrank(root,x);}
int findwei(int x){return findwei(root,x);}
int findqian(int x)
{
int ans=;findqian(root,x,ans);
return ans;
}
int findhou(int x)
{
int ans=;findhou(root,x,ans);
return !ans?inf:ans;
}
}t[];
int qi[];
void build(int k,int l,int r,int x)
{
t[k].l=l,t[k].r=r,t[k].add(qi[x]);
if(l==r)return ;int mid=(l+r)>>;
if(x<=mid)build(k<<,l,mid,x);
else build(k<<|,mid+,r,x);
}
int findrank(int k,int l,int r,int x)
{
if(t[k].l>=l&&t[k].r<=r)return t[k].findrank(x);
int mid=(t[k].l+t[k].r)>>,p1=k<<,p2=p1|;
if(r<=mid)return findrank(p1,l,r,x);
if(l>mid)return findrank(p2,l,r,x);
return findrank(p1,l,r,x)+findrank(p2,l,r,x);
}
int findqian(int k,int l,int r,int x)
{
if(t[k].l>=l&&t[k].r<=r)return t[k].findqian(x);
int mid=(t[k].l+t[k].r)>>,p1=k<<,p2=p1|;
if(r<=mid)return findqian(p1,l,r,x);
if(l>mid)return findqian(p2,l,r,x);
return max(findqian(p1,l,r,x),findqian(p2,l,r,x));
}
int findhou(int k,int l,int r,int x)
{
if(t[k].l>=l&&t[k].r<=r)return t[k].findhou(x);
int mid=(t[k].l+t[k].r)>>,p1=k<<,p2=p1|;
if(r<=mid)return findhou(p1,l,r,x);
if(l>mid)return findhou(p2,l,r,x);
return min(findhou(p1,l,r,x),findhou(p2,l,r,x));
}
int findwei(int l,int r,int x)
{
int ll=,rr=inf,mid,ans;
while(ll<=rr)
{
mid=(ll+rr)>>;
int rank=findrank(,l,r,mid)+;
if(rank<=x)ans=mid,ll=mid+;else rr=mid-;
}
return findqian(,l,r,ans+);
}
void change(int k,int x,int w)
{
t[k].del(qi[x]),t[k].add(w);
if(t[k].l==t[k].r)return ;
int mid=(t[k].l+t[k].r)>>;
if(x<=mid)change(k<<,x,w);
else change(k<<|,x,w);
}
int n,m;
int CSC()
{
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
inin(n),inin(m);
re(i,,n)inin(qi[i]);
re(i,,n)build(,,n,i);
re(i,,m)
{
int opt,q,ww,e;
inin(opt);
if(opt==)
{
inin(q),inin(ww),inin(e);
printf("%d\n",findrank(,q,ww,e)+);
}
else if(opt==)
{
inin(q),inin(ww),inin(e);
printf("%d\n",findwei(q,ww,e));
}
else if(opt==)
{
inin(q),inin(ww);
change(,q,ww);qi[q]=ww;
}
else if(opt==)
{
inin(q),inin(ww),inin(e);
printf("%d\n",findqian(,q,ww,e));
}
else
{
inin(q),inin(ww),inin(e);int ret=findhou(,q,ww,e);
// printf("%d\n",ret==inf?0:ret);
printf("%d\n",ret);
}
}
return ;
}

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

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

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

  2. bzoj3196 二逼平衡树 树状数组套线段树

    题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...

  3. bzoj3196 二逼平衡树 树套树(线段树套Treap)

    Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 4697  Solved: 1798[Submit][Status][D ...

  4. BZOJ3196 二逼平衡树 ZKW线段树套vector(滑稽)

    我实在是不想再打一遍树状数组套替罪羊树了... 然后在普通平衡树瞎逛的时候找到了以前看过vector题解 于是我想:为啥不把平衡树换成vector呢??? 然后我又去学了一下ZKW线段树 就用ZKW线 ...

  5. [BZOJ3196] 二逼平衡树 [权值线段树套位置平衡树]

    题面 洛咕题面 思路 没错我就是要不走寻常路! 看看那些外层位置数据结构,必须二分的,$O(n\log^3 n)$的做法吧! 看看那些cdq分治/树状数组套线段树的,空间$O(n\log^2 n)$挤 ...

  6. BZOJ3196 二逼平衡树 【线段树套平衡树】

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

  7. BZOJ3196——二逼平衡树

    1.题目大意:给你一个序列,有5种操作,都有什么呢... 1> 区间第k小 这个直接用二分+树套树做 2> 区间小于k的有多少 这个直接用树套树做 3> 单点修改 这个直接用树套树做 ...

  8. luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)

    带修改区间K大值 这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做 时空都是$O(nlog^2n)$的(如果离散化了的话 ...

  9. BZOJ3196:二逼平衡树(线段树套Splay)

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

随机推荐

  1. FastReport快速安装教程

    安装后需要覆盖的文件全部复制到安装目录 替换后的安装目录 选中Recompile右键必须以管理员运行 看图选择 编译后,需要汉化的话看下图选择 怎么添加Library直接看图按顺序进行 选择insta ...

  2. oracle添加字段,备注

    1.添加字段: alter table  表名  add (字段  字段类型)  [ default  '输入默认值']  [null/not null]  ; 2.添加备注: comment on ...

  3. sap 申请 新系统用户

    1:打开sap  logon, 进入到以下界面,connection上面 ,右键>add new entry 2: 搜索自己需要的系统名称. 3:一直next,直到完成 4: 双击该系统,进入以 ...

  4. docker 在宿主机上根据进程PID查找归属容器ID

    在使用docker时经常出现一台docker主机上跑了多个容器,可能其中一个容器里的进程导致了整个宿主机load很高,其实一条命令就可以找出罪魁祸首 #查找容器ID docker inspect -f ...

  5. 更新合并数组的es6方法

  6. iOS 测试企业应用的分发

    开发者能够方便地来做iOS应用的测试分发,目前可以选用“浦公英”和“Fir.im”来做. 生成IPA文件 生成应用的 IPA 文件可以使用命令行 xcodebuild exportArchive -e ...

  7. gcc常用命令使用

    gcc编译文件过程 .c文件到 .i文件 到.s(汇编文件) 到.o文件,再到可执行文件 .c到.i 实操一下: test.c文件如下 : #include <stdlib.h> #inc ...

  8. string.Format格式化输出

    staticstring Format (string format,object arg0):将指定字符串中的一个或多个格式项替换为指定对象的字符串表示形式 (1)格式化货币(跟系统的环境有关,中文 ...

  9. Bug 5323844-IMPDP无法导入远程数据库同义词的同义词

    参见MOS文档: Bug 5323844 - SYNONYM for a SYNONYM in remote database not imported using IMPDP (文档 ID 5323 ...

  10. oracle 常用(一)

    常用的6个分组函数: 注意点:where字句中不能使用组函数.要用到having函数. 但是从优化角度看,尽量使用where avg :平均值           sum:求和            ...