当前位置: 首页 > news >正文

树套树

P3380 【模板】树套树

这里采取的是线段树套平衡树(FHQ)

考虑树套树可以解决类似于在两维区间限制类似操作的问题

把线段树上每个节点维护一颗平衡树,维护的方法也非常简单,发现只要知道root,就能够访问平衡树,非常简单

考虑每个节点会被添加log次,所以平衡树要 nlogn 个节点,线段树普通 4n 个节点

考虑二操作,就二分一下排名的数,查排名,\(log^3\)

修改操作,把所有包含修改节点的平衡树进行修改

注意!!!!!!!(血淋淋的教训,我调了好几个小时)

平衡树添加节点一定要按照顺序合并,即先按照排名分裂,在依次合并,保证满足二叉树性质,这个在添加节点和修改节点时都要满足

查排名是查有多少个小于x的数,因为我们答案最终是要累加起来,别忘了最后+1

修改节点时一定要把修改出来的节点,所有的变量都初始化!!!

#include<bits/stdc++.h>
#define ls(x) dt[x].ls
#define rs(x) dt[x].rs
#define pri(x) dt[x].pri
#define key(x) dt[x].key
#define siz(x) dt[x].siz
using namespace std;
const int N=5e4+5,M=1e8;
int cnt,n,m;
int a[N];
struct node{int root,key;
}tr[N*4];
struct dot{int ls,rs,pri,key,siz;
}dt[N*20];
struct FHQ{int newnode(int x){dt[++cnt]={0,0,rand(),x,1};return cnt;}void update(int u){siz(u)=siz(ls(u))+siz(rs(u))+1;}void split(int u,int x,int &L,int &R){if(u==0){L=R=0;return;}if(key(u)<=x){L=u;split(rs(u),x,rs(u),R);}else{R=u;split(ls(u),x,L,ls(u));}update(u);}int merge(int L,int R){if(!L||!R)  return L+R;if(pri(L)<pri(R)){rs(L)=merge(rs(L),R);update(L);return L;}else{ls(R)=merge(L,ls(R));update(R);return R;}}void insert(int &root,int l,int r){//RE表明没写返回值for(int i=l;i<=r;i++){int L,R;split(root,a[i],L,R);root=merge(L,merge(newnode(a[i]),R));}}int rank(int &root,int x){int L,R;split(root,x-1,L,R);int res=siz(L);//这里要判断是否已经全满了root=merge(L,R);return res;}int find(int u,int k){if(!u) return -1;if(siz(ls(u))+1==k)  return key(u);else if(siz(ls(u))+1<k)  return find(rs(u),k-siz(ls(u))-1);else  return find(ls(u),k);}void change(int &root,int x,int k){int L,R,p=0;split(root,x-1,L,R);split(R,x,p,R);int g=p;p=merge(ls(p),rs(p));root=merge(L,merge(p,R));//插入一定是要有顺序的split(root,k,L,R);if(g){dt[g]={0,0,rand(),k,1};//一定要全部修改root=merge(L,merge(g,R));}}int pre(int &root,int x){int L,R;split(root,x-1,L,R);int res=find(L,siz(L));if(res==-1)  res=-2147483647;root=merge(L,R);return res;}int suc(int &root,int x){int L,R;split(root,x,L,R);int res=find(R,1);if(res==-1)  res=2147483647;root=merge(L,R);return res;}void print(int u){if(!u)  return;print(ls(u));printf("%d ",key(u));print(rs(u));}
}FHQ;
struct tree{void build(int k,int l,int r){FHQ.insert(tr[k].root,l,r);if(l==r){tr[k].key=a[l];return;}int mid=(l+r)>>1;build(k*2,l,mid);build(k*2+1,mid+1,r);}void change(int k,int l,int r,int x,int g){FHQ.change(tr[k].root,a[x],g);if(l==r){return;}int mid=(l+r)>>1;if(x<=mid)  change(k*2,l,mid,x,g);else  change(k*2+1,mid+1,r,x,g);}void she(int &res,int op){if(op==1)  res=0;if(op==2)  res=-2147483647;if(op==3)  res=2147483647;}void update(int &res,int op,int num){if(op==1)  res+=num;if(op==2)  res=max(res,num);if(op==3)  res=min(res,num);}int figue(int k,int g,int op){if(op==1)  return FHQ.rank(tr[k].root,g);if(op==2)  return FHQ.pre(tr[k].root,g);if(op==3)  return FHQ.suc(tr[k].root,g);}int query(int k,int l,int r,int x,int y,int g,int op){if(x<=l&&r<=y){return figue(k,g,op);}int mid=(l+r)>>1,res;she(res,op);if(x<=mid)  update(res,op,query(k*2,l,mid,x,y,g,op));if(y>mid)  update(res,op,query(k*2+1,mid+1,r,x,y,g,op));return res;}int middle(int x,int y,int k){int l=0,r=M;while(l<r){int mid=(l+r+1)>>1;if(query(1,1,n,x,y,mid,1)+1<=k)  l=mid;else  r=mid-1;}return l;}
}tree;
int main(){srand(time(NULL));scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",&a[i]);}tree.build(1,1,n);for(int i=1;i<=m;i++){int op,l,r,k;scanf("%d%d%d",&op,&l,&r);if(op==1){scanf("%d",&k);printf("%d\n",tree.query(1,1,n,l,r,k,1)+1);}if(op==2){scanf("%d",&k);printf("%d\n",tree.middle(l,r,k));}if(op==3){tree.change(1,1,n,l,r);a[l]=r;}if(op==4){scanf("%d",&k);printf("%d\n",tree.query(1,1,n,l,r,k,2));}if(op==5){scanf("%d",&k);printf("%d\n",tree.query(1,1,n,l,r,k,3));}}return 0;
}
http://www.wxhsa.cn/company.asp?id=1266

相关文章:

  • 复制R包
  • 【Azure Developer】Java代码实现获取Azure 资源的指标数据却报错 invalid time interval input
  • 小记基环树上的最大独立集
  • 2025京东方全球创新伙伴大会隆重举行 AI焕新驱动产业质变跃迁
  • 张量链式法则(上篇):任意维度反向传播公式推导与常见算子解析
  • GAS_Aura-Aura Input Component
  • CF739C Alyona and towers
  • VMware Workstation 17.5.2 Build 23775571
  • 编程要求
  • qoj1828 TraveLog
  • CF827D Best Edge Weight
  • 基于 YOLOv8 和 Streamlit 搭建视频实时目标跟踪与分割 Web 应用的完整流程
  • win10休眠失败_自动启动 解决办法
  • 新人必看:入职第一个月,如何快速熟悉业务并开始测试?
  • 202210_QQ群_神秘的压缩包
  • 人闲的时候
  • 第一周作业
  • [杂谈] 关于听的音乐
  • C# GC
  • CCPC 2024 郑州 个人题解
  • Pollard Rho 分解质因数
  • 7777
  • [豪の学习笔记] 软考中级备考 基础复习#7
  • 经典面试题目:二叉树遍历
  • 十、微程序控制器是什么?
  • 2023CCPC秦皇岛站
  • 2
  • 1
  • 基本数据类型
  • 二、指令执行过程