什么时候需要使用树套树呢?在很多条件需要你使用一种树形结构维护,同时又加上了区间或是其它格外的限制时,可以使用树套树。像让你维护区间第k大,区间排名之类的两种数据结构的功能综合到了一道题中时。
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5;
#define int int
struct node{
int lc,rc;
int key,value;
int size;
}e[10000000+10];
int tot,a[N],n,m;
int read()
{
char ch = getchar();
int x = 0, flag = 1;
while (ch != '-' && (ch < '0' || ch > '9'))
ch = getchar();
if (ch == '-')
{
ch = getchar();
flag = -1;
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * flag;
}
struct FHQ_TEAP{
int root=0;
int new_t(int x){
e[++tot].size=1;
e[tot].value=x;
e[tot].key=rand();
return tot;
}
void update(int x){
e[x].size=e[e[x].lc].size+e[e[x].rc].size+1;
return ;
}
void split(int x,int k,int &a,int &b){
if(!x){
a=b=0;
return ;
}
if(e[x].value<=k){
a=x;
split(e[x].rc,k,e[x].rc,b);
update(x);
}
else{
b=x;
split(e[x].lc,k,a,e[x].lc);
update(x);
}
return ;
}
int merge(int a,int b){
if(!a||!b)return a+b;
if(e[a].key<e[b].key){
e[a].rc=merge(e[a].rc,b);
update(a);
return a;
}
else{
e[b].lc=merge(a,e[b].lc);
update(b);
return b;
}
}
void init(int k){
int a,b;
split(root,k,a,b);
root=merge(merge(a,new_t(k)),b);
return ;
}
void outint(int k){
int a,b,c;
split(root,k,a,b);
split(a,k-1,a,c);
c=merge(e[c].lc,e[c].rc);
root=merge(merge(a,c),b);
return ;
}
void build(int l,int r){
for(int i=l;i<=r;i++){
init(a[i]);
}
}
int findrank(int k){
int a,b,ans;
split(root,k-1,a,b);
ans=e[a].size;
root=merge(a,b);
return ans;
}
int ask(int x,int k){
if(e[e[x].lc].size>=k)return ask(e[x].lc,k);
else if(e[e[x].lc].size+1==k)return e[x].value;
else return ask(e[x].rc,k-e[e[x].lc].size-1);
}
int query_pre(int k){
int a,b;
split(root,k-1,a,b);
int ans;
if(e[a].size==0){
root=merge(a,b);
return -2147483647;
}
ans=ask(a,e[a].size);
root=merge(a,b);
return ans;
}
int query_suf(int k){
int a,b;
split(root,k,a,b);
int ans;
if(e[b].size==0){
root=merge(a,b);
return 2147483647;
}
ans=ask(b,1);
root=merge(a,b);
return ans;
}
}FT[N<<2];
struct XIANDUANSHU{
void build(int rt,int l,int r){
FT[rt].build(l,r);
if(l!=r){
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
}
int find_rank(int rt,int l,int r,int L,int R,int k){
int ans=0;
if(L<=l&&r<=R){
ans=FT[rt].findrank(k);
return ans;
}
int mid=(l+r)>>1;
if(L<=mid)ans+=find_rank(rt<<1,l,mid,L,R,k);
if(mid+1<=R)ans+=find_rank(rt<<1|1,mid+1,r,L,R,k);
return ans;
}
int find_k(int l,int r,int rank){
int a=0,b=1e8,mid,sum,ans=-1;
mid=(a+b)>>1;
while(a<=b){
mid=(a+b)>>1;
sum=find_rank(1,1,n,l,r,mid);
if(sum+1<=rank){
ans=mid;
a=mid+1;
}
else b=mid-1;
}
return ans;
}
void change(int rt,int l,int r,int x,int k){
int mid=(l+r)>>1;
FT[rt].outint(a[x]);
FT[rt].init(k);
if(l==r)return ;
if(x<=mid)change(rt<<1,l,mid,x,k);
else change(rt<<1|1,mid+1,r,x,k);
return ;
}
int qianqu(int rt,int l,int r,int L,int R,int k){
int ans=-2147483647;
if(L<=l&&r<=R){
return FT[rt].query_pre(k);
}
int mid=(l+r)>>1;
if(l==r)return ans;
if(L<=mid)ans=max(ans,qianqu(rt<<1,l,mid,L,R,k));
if(mid+1<=R)ans=max(qianqu(rt<<1|1,mid+1,r,L,R,k),ans);
return ans;
}
int houji(int rt,int l,int r,int L,int R,int k){
int ans=2147483647;
if(L<=l&&r<=R){
return FT[rt].query_suf(k);
}
int mid=(l+r)>>1;
if(l==r)return ans;
if(L<=mid)ans=min(ans,houji(rt<<1,l,mid,L,R,k));
if(mid+1<=R)ans=min(houji(rt<<1|1,mid+1,r,L,R,k),ans);
return ans;
}
}ST;
int main(){
n=read();
m=read();
for(int i=1;i<=n;i++)a[i]=read();
ST.build(1,1,n);
for(int i=1;i<=m;i++){
int x,opt,l,r,k;
opt=read();
if(opt==1){
l=read(),r=read(),k=read();
printf("%d\n",ST.find_rank(1,1,n,l,r,k)+1);
}
if(opt==2){
l=read(),r=read(),k=read();
printf("%d\n",ST.find_k(l,r,k));
}
if(opt==3){
x=read(),k=read();
ST.change(1,1,n,x,k);
a[x]=k;
}
if(opt==4){
l=read(),r=read(),k=read();
printf("%d\n",ST.qianqu(1,1,n,l,r,k));
}
if(opt==5){
l=read(),r=read(),k=read();
printf("%d\n",ST.houji(1,1,n,l,r,k));
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效