社区讨论
萌新刚学OI两年半,求助一道树套树,悬赏三关
P3380【模板】树套树参与者 1已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @lo2afvz4
- 此快照首次捕获于
- 2023/10/23 10:38 2 年前
- 此快照最后确认于
- 2023/11/03 10:49 2 年前
rt,前三个操作没问题,貌似是前驱后继写挂了
CPP#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10,inf=2147483647;
namespace FHQ{
struct node{
int x,rnd,size;
int ls,rs;
}tr[N];
int tot=0;
class fhq{
public:
int root;
fhq(){
root=0;
}
int newNode(int x){
tr[++tot]={x,rand(),1,0,0};
return tot;
}
inline void pushup(int x){
tr[x].size=tr[tr[x].ls].size+tr[tr[x].rs].size+1;
}
void split(int u,int &x,int &y,int val){
if(!u){
x=y=0;
return;
}
if(tr[u].x<=val) x=u,split(tr[x].rs,tr[x].rs,y,val);
else y=u,split(tr[y].ls,x,tr[y].ls,val);
pushup(u);
}
int merge(int x,int y){
if(!x||!y) return x+y;
if(tr[x].rnd<tr[y].rnd){
tr[x].rs=merge(tr[x].rs,y);
pushup(x);
return x;
}
else{
tr[y].ls=merge(x,tr[y].ls);
pushup(y);
return y;
}
}
void insert(int x){
int l,r;
split(root,l,r,x);
root=merge(l,merge(newNode(x),r));
}
void del(int x){
int l,r,xx,yy;
split(root,l,r,x);
split(l,xx,yy,x-1);
yy=merge(tr[yy].ls,tr[yy].rs);
root=merge(merge(xx,yy),r);
}
int rnk(int x){
int l,r;
split(root,l,r,x-1);
int tmp=tr[l].size+1;
root=merge(l,r);
return tmp;
}
int kth(int u,int k){
int p=tr[tr[u].ls].size+1;
if(k==p) return tr[u].x;
if(k<p) return kth(tr[u].ls,k);
return kth(tr[u].rs,k-p);
}
int getKth(int x){
return kth(root,x);
}
int pre(int x){
int l,r;
split(root,l,r,x-1);
int tmp=kth(l,tr[l].size);
root=merge(l,r);
return tmp;
}
int nxt(int x){
int l,r;
split(root,l,r,x);
int tmp=kth(r,1);
root=merge(l,r);
return tmp;
}
};
}
struct node{
FHQ::fhq tree;
int l,r;
}tr[N];
int a[N];
int n,m;
void build(int x,int l,int r){
tr[x].l=l,tr[x].r=r;
for(int i=l;i<=r;i++) tr[x].tree.insert(a[i]);
if(l==r) return;
int mid=(l+r)/2;
build(x*2,l,mid),build(x*2+1,mid+1,r);
}
int rnk(int x,int l,int r,int k){
if(tr[x].l>=l&&tr[x].r<=r) return tr[x].tree.rnk(k)-1;
int mid=(tr[x].l+tr[x].r)/2,res=0;
if(l<=mid) res=rnk(x*2,l,r,k);
if(r>mid) res+=rnk(x*2+1,l,r,k);
return res;
}
int kth(int l,int r,int k){
int x=0,y=1e8+10;
while(x<y){
int mid=(x+y+1)/2,tmp=rnk(1,l,r,mid);
if(tmp>=k) y=mid-1;
else x=mid;
}
return x;
}
int pre(int x,int l,int r,int k){
if(tr[x].l>=l&&tr[x].r<=r) return tr[x].tree.pre(k);
int mid=(tr[x].l+tr[x].r)/2,maxx=-inf;
if(l<=mid) maxx=max(maxx,pre(x*2,l,r,k));
if(r>mid) maxx=max(maxx,pre(x*2+1,l,r,k));
return maxx;
}
int nxt(int x,int l,int r,int k){
if(tr[x].l>=l&&tr[x].r<=r) return tr[x].tree.nxt(k);
int mid=(tr[x].l+tr[x].r)/2,minn=inf;
if(l<=mid) minn=min(minn,nxt(x*2,l,r,k));
if(r>mid) minn=min(minn,nxt(x*2+1,l,r,k));
return minn;
}
int change(int x,int k,int p){
if(tr[x].l==tr[x].r){
int tmp=tr[x].tree.getKth(1);
tr[x].tree.del(tmp);
tr[x].tree.insert(p);
return tmp;
}
int mid=(tr[x].l+tr[x].r)/2,tmp=0;
if(k<=mid) tmp=change(x*2,k,p);
else tmp=change(x*2+1,k,p);
tr[x].tree.del(tmp);
tr[x].tree.insert(p);
return tmp;
}
int main(){
srand(19260817);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
while(m--){
int opt,l,r,k;
cin>>opt>>l>>r;
if(opt!=3) cin>>k;
if(opt==1) cout<<rnk(1,l,r,k)+1<<endl;
if(opt==2) cout<<kth(l,r,k)<<endl;
if(opt==3) change(1,l,r);
if(opt==4) cout<<pre(1,l,r,k)<<endl;
if(opt==5) cout<<nxt(1,l,r,k)<<endl;
}
}
回复
共 1 条回复,欢迎继续交流。
正在加载回复...