求各位大佬帮忙看看哪里有问题,蒟蒻从下午开始写调到晚上还是没调出来,目前知道的是查询排名为k的值和前驱后继问题较大,但左调右调调不出来,可能是前面模板写的不太对,因为线段树和treap也是两周内刚学的写的有点蒙,如果有大佬愿意调我的垃圾代码我真的会非非非非非常感谢
#include<bits/stdc++.h>
using namespace std;
const int M=5e4;
int n,m,a[M];
//题意
struct treap_node{
int l,r,cnt,val,rnd,size;
}tb[M*4];//平衡树单点信息
int tot;
struct FHQ_treap{//打包一个平衡树
int root;
inline int newnode(int v) {//新建节点
tb[++tot].val = v;
tb[tot].rnd = rand();
tb[tot].size = 1;
return tot;
}
inline void pushup(int p){
tb[p].size=tb[tb[p].l].size+tb[tb[p].r].size+1;
return ;
}
// 编号 按v分裂 左右子树编号
inline void split(int p,int v,int &x,int &y){
if(!p){x=y=0;return;}//空树
if(tb[p].val<=v){//右子树要被分裂
x=p;
split(tb[p].r,v,tb[p].r,y);
}
else{
y=p;
split(tb[p].l,v,x,tb[p].l);
}
pushup(p);
}
// 两个根节点
inline int merge(int x,int y){//合并两颗treap 返回值是根节点编号
if(!x||!y){
return x+y;
}
if(tb[x].rnd<tb[y].rnd){//按堆的性质小的放上面当根
merge(tb[x].r,y);
pushup(x);
return x;
}else{
merge(x,tb[y].l);
pushup(y);
return y;
}
}
inline void insert(int v){
int x,y;
split(root,v,x,y);
int z=newnode(v);
root=merge(merge(x,z),y);
return ;
}
inline void del(int v){
int x,y,z;
//剖出"v"
split(root,v,x,z);
split(x,v-1,x,y);
y=merge(tb[y].l,tb[y].r);
root=merge(merge(x,y),z);
return ;
}
inline int _rank(int v){//就是小于v的节点数+1
int x,y,ans;
split(root,v-1,x,y);
if(tb[x].size)
ans=tb[x].size+1;
root=merge(x,y);
return ans;
}
inline int topk(int p,int k){
int lsz=tb[tb[p].l].size;
if(lsz+1==k){//说明topk是当前节点
return tb[p].val;
}else if(lsz+1<k){//在右子树
return topk(tb[p].r,k-lsz-1);
}else if(lsz+1>k){
return topk(tb[p].l,k);
}
}
inline int get_pre(int v){
int x,y,ans;
split(root,v-1,x,y);
//x都小于v
if(tb[x].size)
ans=topk(x,tb[x].size);
else
ans=INT_MIN;
root=merge(x,y);
return ans;
}
inline int get_suc(int v){
int x,y,ans;
split(root,v,x,y);
if(tb[y].size)
ans=topk(y,1);
else
ans=INT_MAX;
root=merge(x,y);
return ans;
}
};
#define lson (i<<1)
#define rson (i<<1|1)
//这里有一些宏定义
struct seg_node{
int l,r;
FHQ_treap tx;
}ts[M*4];
inline void build_tree(int i,int l,int r){
ts[i].l=l;
ts[i].r=r;
for(int j=l;j<=r;j++){
ts[i].tx.insert(a[j]);
}
if(l==r){
return ;
}
int mid=(l+r)/2;
build_tree(lson,l,mid);
build_tree(rson,mid+1,r);
}
inline void change(int i,int p,int k){
ts[i].tx.del(a[p]);
ts[i].tx.insert(k);
if(ts[i].l==ts[i].r){
return;
}
int mid=(ts[i].l+ts[i].r)/2;
if(p<=mid){//左儿子还得改
change(lson,p,k);
}
else if(p>mid){//右儿子还得改
change(rson,p,k);
}
return ;
}
inline int query_rank(int i,int l,int r,int k){//排名
if(ts[i].l>r || ts[i].r<l){
return 0;
}
if(l<=ts[i].l&& ts[i].r<=r){
return ts[i].tx._rank(k)-1;
}
//分别在左右孩子里找
return query_rank(lson,l,r,k)+query_rank(rson,l,r,k);
}
inline int query_topk(int l,int r,int k){//这里不知道什么东西错了
int x=0,y=1e8,ans=0;//二分答案
while(x<=y){
int mid=(x+y)/2;
//cout<<query_rank(1,l,r,mid)<<" ";一直是2???
if(query_rank(1,l,r,mid)+1<=k){
ans=mid;
x=mid+1;
}else{
y=mid-1;
}
}
return ans;
}
inline int query_pre(int i,int l,int r,int v){
if(ts[i].l>r || ts[i].r<l){
return INT_MIN;
}
if(l<=ts[i].l && ts[i].r<=r){
return ts[i].tx.get_pre(v);
}
return max(query_pre(lson,l,r,v),query_pre(rson,l,r,v));
}
inline int query_suc(int i,int l,int r,int v){
if(ts[i].l>r || ts[i].r<l){
return INT_MAX;
}
if(l<=ts[i].l && r>=ts[i].r){
return ts[i].tx.get_suc(v);
}
return min(query_suc(lson,l,r,v),query_suc(rson,l,r,v));
}
int main(){
srand('线段树和平衡树放过我吧');
// ios::sync_with_stdio(0);
// cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build_tree(1,1,n);
for(int i=1;i<=m;i++){
int opt,l,r,k,pos;
cin>>opt;
if(opt==1){
cin>>l>>r>>k;
cout<<query_rank(1,l,r,k)+1<<'\n';
}
if(opt==2){
cin>>l>>r>>k;
cout<<query_topk(l,r,k)<<'\n';
}
if(opt==3){
cin>>pos>>k;
change(1,pos,k);
a[pos]=k;
}
if(opt==4){
cin>>l>>r>>k;
cout<<query_pre(1,l,r,k)<<'\n';
}
if(opt==5){
cin>>l>>r>>k;
cout<<query_suc(1,l,r,k)<<'\n';
}
}
return 0;
}