[模板] 主席树

本质上是多棵线段树,动态开点,每次修改到root的一条链节约空间

 

可持久化数组(维护叶子节点的主席树)

#include<iostream>
#include<cstdio>

using namespace std;

inline int rd(){
  int ret=0,f=1;char c;
  while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
  while(isdigit(c))ret=ret*10+c-'0',c=getchar();
  return ret*f;
}

const int MAXN = 1000005;

int n,m;
int a[MAXN],rt[MAXN];

int nodenum,ch[MAXN*40][2],val[MAXN*40];
inline int newnode(){return ++nodenum;}
void build(int &cur,int l,int r){
  cur=newnode();
  if(l==r){val[cur]=a[l];return;}
  int mid=(l+r)>>1;
  build(ch[cur][0],l,mid);
  build(ch[cur][1],mid+1,r);
}
void update(int &cur,int pre,int l,int r,int x,int w){
  if(!cur)cur=newnode();
  val[cur]=val[pre];
  if(l==r){val[cur]=w;return;}
  int mid=(l+r)>>1;
  if(x<=mid) update(ch[cur][0],ch[pre][0],l,mid,x,w),ch[cur][1]=ch[pre][1];
  else update(ch[cur][1],ch[pre][1],mid+1,r,x,w),ch[cur][0]=ch[pre][0];
}
int query(int cur,int l,int r,int x){
  if(l==r)return val[cur];
  int mid=(l+r)>>1;
  if(x<=mid) return query(ch[cur][0],l,mid,x);
  return query(ch[cur][1],mid+1,r,x);
}

int main(){
  n=rd();m=rd();
  for(int i=1;i<=n;i++){
    a[i]=rd();
  }
  build(rt[0],1,n);
  int x,y,z,w;
  for(int i=1;i<=m;i++){
    x=rd();y=rd();z=rd();
    if(y==1){
      w=rd();
      update(rt[i],rt[x],1,n,z,w);
    }else{
      printf("%d\n",query(rt[x],1,n,z));
      rt[i]=rt[x];
    }
  }
  return 0;
}
View Code

 

posted @ 2018-04-28 23:59  GhostCai  阅读(154)  评论(0编辑  收藏  举报