20230630-可持久化数据结构 2

发布时间 2023-07-19 22:51:30作者: H_W_Y

20230630

P3919 【模板】可持久化线段树 1(可持久化数组)

题目大意

传送门
题目已经说得很清楚了

Solution

一道可持久化线段树的板子题
注意数组开大一点!!!

H_W_Y-Coding
#include <bits/stdc++.h>
using namespace std;

const int maxn=2e6+10;//开大一点
int n,m,a[maxn],rt[maxn],tot=0,op,x,val,p;
struct  seg{
  int val,ch[2];
}tr[maxn<<4];

namespace SGT{
  #define lc tr[p].ch[0]
  #define rc tr[p].ch[1]
  inline void build(int &p,int l=1,int r=n){
  	p=++tot;
  	if(l==r){
  	  tr[p].val=a[l];
	  return ;	
	}
	int mid=l+((r-l)>>1);
	build(lc,l,mid);
	build(rc,mid+1,r);
  }
  inline void update(int &p,int pre,int x,int val,int l=1,int r=n){
  	p=++tot;
  	tr[p].val=tr[pre].val;
  	tr[p].ch[0]=tr[pre].ch[0];
  	tr[p].ch[1]=tr[pre].ch[1];
  	if(l==r){
	  tr[p].val=val;
	  return ;  
	}
	int mid=l+((r-l)>>1);
	if(x<=mid) update(lc,tr[pre].ch[0],x,val,l,mid);
	else update(rc,tr[pre].ch[1],x,val,mid+1,r);
  }
  inline int query(int p,int x,int l=1,int r=n){
  	if(l==r) return tr[p].val;
  	int mid=l+((r-l)>>1);
    if(x<=mid) return query(lc,x,l,mid);
    else return query(rc,x,mid+1,r);
  }
}
using namespace SGT;

int main(){
  /*2023.7.6 H_W_Y P3919 【模板】可持久化线段树 1(可持久化数组) 可持久化线段树*/ 
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++) scanf("%d",&a[i]);
  build(rt[0]);
  for(int i=1;i<=m;i++){
  	scanf("%d%d",&p,&op);
  	if(op==1){
  	  scanf("%d%d",&x,&val);
	  update(rt[i],rt[p],x,val);
	}
	else{
	  scanf("%d",&x);
	  printf("%d\n",query(rt[p],x));
	  rt[i]=++tot;
	  tr[rt[i]]=tr[rt[p]];
	}
  }
  return 0;
}

P3834 【模板】可持久化线段树 2

题目大意

传送门
题目已经说得很清楚了

Solution

第二道板子题

H_W_Y-Coding
#include <bits/stdc++.h>
using namespace std;

const int maxn=2e5+10;
int n,a[maxn],b[maxn],l,r,k,m,rt[maxn],tot=0,len=0;
struct seg{
  int val,ch[2];
}tr[maxn<<4];

namespace SGT{
  #define lc tr[p].ch[0]
  #define rc tr[p].ch[1]
  inline void update(int &p,int pre,int x,int l=0,int r=len){
  	p=++tot;
  	tr[p].val=tr[pre].val+1;
  	tr[p].ch[0]=tr[pre].ch[0];
  	tr[p].ch[1]=tr[pre].ch[1];
  	if(l==r) return ;
  	int mid=l+((r-l)>>1);
  	if(x<=mid) update(lc,tr[pre].ch[0],x,l,mid);
  	else update(rc,tr[pre].ch[1],x,mid+1,r);
  }
  inline int query(int p,int pre,int x,int l=0,int r=len){
  	if(l==r) return l;
  	int mid=l+((r-l)>>1),cnt=tr[lc].val-tr[tr[pre].ch[0]].val;
  	if(x<=cnt) return query(lc,tr[pre].ch[0],x,l,mid);
	else return query(rc,tr[pre].ch[1],x-cnt,mid+1,r); 
  }
}
using namespace SGT;

int main(){
  /*2023.7.6 H_W_Y P3834 【模板】可持久化线段树 2 可持久化线段树*/ 
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
  sort(b+1,b+n+1);
  len=unique(b+1,b+n+1)-b-1;
  for(int i=1;i<=n;i++) update(rt[i],rt[i-1],lower_bound(b+1,b+len+1,a[i])-b);
  for(int i=1;i<=m;i++){
  	scanf("%d%d%d",&l,&r,&k);
  	printf("%d\n",b[query(rt[r],rt[l-1],k)]);
  }
  return 0;
}