A 可持久化线段树
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1e6+10;
const int M=maxn*40;
int a[maxn];
int T[maxn],lson[M],rson[M],c[M];
int n,m,tot;
int build(int l,int r){
int root = tot++;
c[root]=0;
if(l!=r){
int mid=(l+r)>>1;
lson[root]=build(l,mid);
rson[root]=build(mid+1,r);
}
if(l==r)
c[root]=a[l];
return root;
}
int update(int root,int pos,int val){
int newroot=tot++,tmp=newroot;
c[newroot]=0;
int l=1,r=n;
while(l<r){
int mid = (l+r)>>1;
if(pos<=mid){
lson[newroot]=tot++;rson[newroot]=rson[root];
newroot=lson[newroot];root=lson[root];
r=mid;
}
else{
rson[newroot]=tot++;lson[newroot]=lson[root];
newroot=rson[newroot];root=rson[root];
l=mid+1;
}
c[newroot]=0;
}
c[newroot]=val;
return tmp;
}
int query(int root,int pos){
int l=1,r=n;
while(l<r){
int mid=(l+r)>>1;
if(pos<=mid){
r=mid;
root=lson[root];
}
else{
l=mid+1;
root=rson[root];
}
}
if(pos==l)
return c[root];
}
int main()
{
int cnt=0;
tot=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
T[cnt++]=build(1,n);
for(int i=0;i<m;i++){
int aa,bb,cc,dd;
scanf("%d%d",&aa,&bb);
if(bb==1){
scanf("%d%d",&cc,&dd);
T[cnt++]=update(T[aa],cc,dd);
}
else{
scanf("%d",&cc);
printf("%d\n",query(T[aa],cc));
T[cnt++]=T[aa];
}
}
}
B 区间第K小
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 2e5+10;
const int M = maxn*40;
int n,m,q,tot;
int a[maxn],t[maxn];
int T[maxn],lson[M],rson[M],c[M];
void init_hash(){
for(int i = 1;i <= n;i++){
t[i]=a[i];
}
sort(t+1,t+n+1);
m=unique(t+1,t+n+1)-t-1;
}
int Hash(int x){
return lower_bound(t+1,t+1+m,x)-t;
}
int build(int l,int r){
int root=tot++;
c[root]=0;
if(l!=r){
int mid = (l+r)>>1;
lson[root]=build(l,mid);
rson[root]=build(mid+1,r);
}
return root;
}
int update(int root,int pos,int val){
int newroot=tot++,tmp=newroot;
c[newroot]=c[root]+val;
int l=1, r=m;
while(l<r){
int mid=(l+r)>>1;
if(pos<=mid){
lson[newroot] = tot++;rson[newroot] = rson[root];
newroot = lson[newroot]; root = lson[root];
r=mid;
}
else{
rson[newroot] = tot++;lson[newroot] = lson[root];
newroot = rson[newroot]; root = rson[root];
l=mid+1;
}
c[newroot]=c[root]+val;
}
return tmp;
}
int query(int left_root,int right_root,int k){
int l = 1,r = m;
while(l<r){
int mid = (l+r)>>1;
if(c[lson[left_root]]-c[lson[right_root]]>=k){
r=mid;
left_root=lson[left_root];
right_root=lson[right_root];
}
else{
l=mid+1;
k-=c[lson[left_root]]-c[lson[right_root]];
left_root = rson[left_root];
right_root = rson[right_root];
}
}
return l;
}
int main()
{
while(~scanf("%d%d",&n,&q)){
tot=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
init_hash();
T[n+1]=build(1,m);
for(int i=n;i;i--){
int pos = Hash(a[i]);
T[i]=update(T[i+1],pos,1);
}
while(q--){
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",t[query(T[l],T[r+1],k)]);
}
}
return 0;
}
C 可持久化并查集
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 2e3+10;
const int M=maxn*80;
int T[maxn],lson[M],rson[M],per[M],dep[M];
int n,m,tot;
void build(int &rt,int l,int r)
{
rt=++tot;
if(l==r){
per[rt]=l;
return;
}
int mid=(l+r)>>1;
build(lson[rt],l,mid);
build(rson[rt],mid+1,r);
}
void merge(int last,int &rt,int l,int r,int pos,int fa)
{
rt=++tot;lson[rt]=lson[last],rson[rt]=rson[last];
if(l==r){
per[rt]=fa;
dep[rt]=dep[last];
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) merge(lson[last],lson[rt],l,mid,pos,fa);
else merge(rson[last],rson[rt],mid+1,r,pos,fa);
}
void update(int rt,int l,int r,int pos)
{
if(l==r){
dep[rt]++;
return;
}
int mid=(l+r)>>1;
if(pos<=mid)update(lson[rt],l,mid,pos);
else update(rson[rt],mid+1,r,pos);
}
int query(int rt,int l,int r,int pos)
{
if(l==r)return rt;
int mid=(l+r)>>1;
if(pos<=mid) return query(lson[rt],l,mid,pos);
else return query(rson[rt],mid+1,r,pos);
}
int find(int rt,int pos)
{
int now=query(rt,1,n,pos);
if(per[now]==pos)return now;
return find(rt,per[now]);
}
int main()
{
tot=0;
scanf("%d%d",&n,&m);
build(T[0],1,n);
for(int i=1;i<=m;i++){
int opt,x,y;
scanf("%d%d",&opt,&x);
if(opt==1){
scanf("%d",&y);
T[i]=T[i-1];
int posx=find(T[i],x);
int posy=find(T[i],y);
if(per[posx]!=per[posy]){
if(dep[posx]>dep[posy])swap(posx,posy);
merge(T[i-1],T[i],1,n,per[posx],per[posy]);
if(dep[posx]==dep[posy])update(T[i],1,n,per[posy]);
}
}
else if(opt==2){
T[i]=T[x];
}
else if(opt==3){
scanf("%d",&y);
T[i]=T[i-1];
int posx,posy;
posx=find(T[i],x);
posy=find(T[i],y);
if(per[posx]==per[posy])printf("1\n");
else printf("0\n");
}
}
return 0;
}