社区讨论
FHQ平衡树T了两个求调
P3380【模板】树套树参与者 3已保存回复 3
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @m22pmh39
- 此快照首次捕获于
- 2024/10/10 10:59 去年
- 此快照最后确认于
- 2025/11/04 17:31 4 个月前
FHQ平衡树T了两个求调
CPP#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=2147483647;
int m,n,cnt,a[50001];
struct node{
int val,key,l,r,size;
}t[40000001];
struct tree{
int l,r,root;
}tr[200001];
int newnode(int val) {
t[++cnt].val=val;
t[cnt].size=1;
t[cnt].key=rand();
return cnt;
}
void push(int x){t[x].size=1+t[t[x].l].size+t[t[x].r].size;}
void sq(int &x,int &y,int k,int p){
if(!p){
x=y=0;
return ;
}
if(t[p].val<=k){
x=p;
sq(t[p].r,y,k,t[p].r);
}
else{
y=p;
sq(x,t[p].l,k,t[p].l);
}
push(p);
}
int merge(int x,int y){
if(!x||!y)return x+y;
if(t[x].key>t[y].key){
t[x].r=merge(t[x].r,y);
push(x);
return x;
}
else {
t[y].l=merge(x,t[y].l);
push(y);
return y;
}
}
void insert(int val,int &root){
int x,y;
sq(x,y,val,root);
root=merge(merge(x,newnode(val)),y);
}
void del(int val,int &root){
int x,y,z;
sq(x,z,val,root);
sq(x,y,val-1,x);
root=merge(merge(x,t[y].l),merge(t[y].r,z));
}
int find_pre(int &root,int k){
int x,y,z,ans;
sq(x,y,k-1,root),z=x;
while(z)ans=t[z].val,z=t[z].r;
root=merge(x,y);
return ans;
}
int find_back(int &root,int k){
int x,y,z,ans;
sq(x,y,k,root),z=y;
while(z)ans=t[z].val,z=t[z].l;
root=merge(x,y);
return ans;
}
int find_rank(int &root,int k){
int x,y,ans;
sq(x,y,k,root);
ans=t[x].size-1;
root=merge(x,y);
return ans;
}
void build(int l,int r,int x){
insert(inf,tr[x].root),insert(-inf,tr[x].root);
tr[x].l=l;tr[x].r=r;
if(l==r)return ;
int mid=(l+r)/2;
build(l,mid,x*2);build(mid+1,r,x*2+1);
}
void change(int p,int x,int kk,int k){
del(kk,tr[x].root),insert(k,tr[x].root);
if(tr[x].l==tr[x].r)return ;
int mid=(tr[x].l+tr[x].r)/2;
if(p<=mid)change(p,x*2,kk,k);
else change(p,x*2+1,kk,k);
}
void seg_insert(int x,int p,int k){
insert(k,tr[x].root);
if(tr[x].l==tr[x].r)return ;
int mid=(tr[x].l+tr[x].r)/2;
if(p<=mid)seg_insert(x*2,p,k);
else seg_insert(x*2+1,p,k);
}
int ask_pre(int l,int r,int x,int k){
if(l<=tr[x].l&&tr[x].r<=r)return find_pre(tr[x].root,k);
int mid=(tr[x].l+tr[x].r)/2,ans=-1e18;
if(l<=mid)ans=max(ans,ask_pre(l,r,x*2,k));
if(r>mid)ans=max(ans,ask_pre(l,r,x*2+1,k));
return ans;
}
int ask_back(int l,int r,int x,int k){
if(l<=tr[x].l&&tr[x].r<=r)return find_back(tr[x].root,k);
int mid=(tr[x].l+tr[x].r)/2,ans=1e18;
if(l<=mid)ans=min(ans,ask_back(l,r,x*2,k));
if(r>mid)ans=min(ans,ask_back(l,r,x*2+1,k));
return ans;
}
int ask_rank(int l,int r,int x,int k){
if(l<=tr[x].l&&tr[x].r<=r)return find_rank(tr[x].root,k);
int mid=(tr[x].l+tr[x].r)/2,ans=0;
if(l<=mid)ans+=ask_rank(l,r,x*2,k);
if(r>mid)ans+=ask_rank(l,r,x*2+1,k);
return ans;
}
int ask_kth(int l,int r,int k){
int ll=0,rr=1e8,ans;
while(ll<=rr){
int mid=(ll+rr)/2;
if(k<ask_rank(l,r,1,mid-1)+1)rr=mid-1;
else ll=mid+1,ans=mid;
}
return ans;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
srand((unsigned)time(0));
cin>>n>>m;
build(1,n,1);
for(int i=1;i<=n;i++)cin>>a[i],seg_insert(1,i,a[i]);
while(m--){
int op,l,r,k;
cin>>op>>l>>r;
if(op==1)cin>>k,cout<<ask_rank(l,r,1,k-1)+1<<'\n';
if(op==2)cin>>k,cout<<ask_kth(l,r,k)<<'\n';
if(op==3)change(l,1,a[l],r),a[l]=r;
if(op==4)cin>>k,cout<<ask_pre(l,r,1,k)<<'\n';
if(op==5)cin>>k,cout<<ask_back(l,r,1,k)<<'\n';
}
}
···
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=2147483647;
int m,n,cnt,a[50001];
struct node{
int val,key,l,r,size;
}t[40000001];
struct tree{
int l,r,root;
}tr[200001];
int newnode(int val) {
t[++cnt].val=val;
t[cnt].size=1;
t[cnt].key=rand();
return cnt;
}
void push(int x){t[x].size=1+t[t[x].l].size+t[t[x].r].size;}
void sq(int &x,int &y,int k,int p){
if(!p){
x=y=0;
return ;
}
if(t[p].val<=k){
x=p;
sq(t[p].r,y,k,t[p].r);
}
else{
y=p;
sq(x,t[p].l,k,t[p].l);
}
push(p);
}
int merge(int x,int y){
if(!x||!y)return x+y;
if(t[x].key>t[y].key){
t[x].r=merge(t[x].r,y);
push(x);
return x;
}
else {
t[y].l=merge(x,t[y].l);
push(y);
return y;
}
}
void insert(int val,int &root){
int x,y;
sq(x,y,val,root);
root=merge(merge(x,newnode(val)),y);
}
void del(int val,int &root){
int x,y,z;
sq(x,z,val,root);
sq(x,y,val-1,x);
root=merge(merge(x,t[y].l),merge(t[y].r,z));
}
int find_pre(int &root,int k){
int x,y,z,ans;
sq(x,y,k-1,root),z=x;
while(z)ans=t[z].val,z=t[z].r;
root=merge(x,y);
return ans;
}
int find_back(int &root,int k){
int x,y,z,ans;
sq(x,y,k,root),z=y;
while(z)ans=t[z].val,z=t[z].l;
root=merge(x,y);
return ans;
}
int find_rank(int &root,int k){
int x,y,ans;
sq(x,y,k,root);
ans=t[x].size-1;
root=merge(x,y);
return ans;
}
void build(int l,int r,int x){
insert(inf,tr[x].root),insert(-inf,tr[x].root);
tr[x].l=l;tr[x].r=r;
if(l==r)return ;
int mid=(l+r)/2;
build(l,mid,x2);build(mid+1,r,x2+1);
}
void change(int p,int x,int kk,int k){
del(kk,tr[x].root),insert(k,tr[x].root);
if(tr[x].l==tr[x].r)return ;
int mid=(tr[x].l+tr[x].r)/2;
if(p<=mid)change(p,x2,kk,k);
else change(p,x2+1,kk,k);
}
void seg_insert(int x,int p,int k){
insert(k,tr[x].root);
if(tr[x].l==tr[x].r)return ;
int mid=(tr[x].l+tr[x].r)/2;
if(p<=mid)seg_insert(x2,p,k);
else seg_insert(x2+1,p,k);
}
int ask_pre(int l,int r,int x,int k){
if(l<=tr[x].l&&tr[x].r<=r)return find_pre(tr[x].root,k);
int mid=(tr[x].l+tr[x].r)/2,ans=-1e18;
if(l<=mid)ans=max(ans,ask_pre(l,r,x2,k));
if(r>mid)ans=max(ans,ask_pre(l,r,x2+1,k));
return ans;
}
int ask_back(int l,int r,int x,int k){
if(l<=tr[x].l&&tr[x].r<=r)return find_back(tr[x].root,k);
int mid=(tr[x].l+tr[x].r)/2,ans=1e18;
if(l<=mid)ans=min(ans,ask_back(l,r,x2,k));
if(r>mid)ans=min(ans,ask_back(l,r,x2+1,k));
return ans;
}
int ask_rank(int l,int r,int x,int k){
if(l<=tr[x].l&&tr[x].r<=r)return find_rank(tr[x].root,k);
int mid=(tr[x].l+tr[x].r)/2,ans=0;
if(l<=mid)ans+=ask_rank(l,r,x2,k);
if(r>mid)ans+=ask_rank(l,r,x2+1,k);
return ans;
}
int ask_kth(int l,int r,int k){
int ll=0,rr=1e8,ans;
while(ll<=rr){
int mid=(ll+rr)/2;
if(k<ask_rank(l,r,1,mid-1)+1)rr=mid-1;
else ll=mid+1,ans=mid;
}
return ans;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
srand((unsigned)time(0));
cin>>n>>m;
build(1,n,1);
for(int i=1;i<=n;i++)cin>>a[i],seg_insert(1,i,a[i]);
while(m--){
int op,l,r,k;
cin>>op>>l>>r;
if(op==1)cin>>k,cout<<ask_rank(l,r,1,k-1)+1<<'\n';
if(op==2)cin>>k,cout<<ask_kth(l,r,k)<<'\n';
if(op==3)change(l,1,a[l],r),a[l]=r;
if(op==4)cin>>k,cout<<ask_pre(l,r,1,k)<<'\n';
if(op==5)cin>>k,cout<<ask_back(l,r,1,k)<<'\n';
}
}
···
回复
共 3 条回复,欢迎继续交流。
正在加载回复...