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

我一直放在任务计划里没做的题qaq

五一集训开始就没做过题了

本来还想一直颓到期中之后,并体验一波掉色,结果并没有达成

因为上信息课太过无聊也不敢在gg面前颓,于是做了这道题

唉本来想半个月都不做了呢www

可持久化数组

就用带修改可持久化线段树来实现w

 这是在luogu题解里看到的图,十分浅显易懂w【侵删

每次都要新建一棵树

节点不能乘二或乘二加一了,编个号3

然后开个数组存一下每次树根的编号就行

#include<cstdio>
#define sev en
using namespace std;
#define N 1000010

struct TREE{
  int l,r,w;
}t[N << 5];
int a[N],root[N],cnt;

int build(int now,int l,int r){
  now = ++cnt;
  if(l == r){
    t[now].w = a[l];
    return cnt;
  }
  int mid = (l + r) >> 1;
  t[now].l = build(now,l,mid);
  t[now].r = build(now,mid + 1,r);
  return now;
}//建树操作

int update(int now){
  cnt++;
  t[cnt] = t[now];
  return cnt;
}//更新树的信息

int modify(int now,int l,int r,int x,int val){
  now = update(now);
  if(l == r)
    t[now].w = val;
  else{
    int mid = (l + r) >> 1;
    if(x <= mid)
      t[now].l = modify(t[now].l,l,mid,x,val);
    else
      t[now].r = modify(t[now].r,mid + 1,r,x,val);
  }
  return now;
}//修改操作

int query(int now,int l,int r,int x){
  if(l == r)
    return t[now].w;
  int mid = (l + r) >> 1;
  if(x <= mid)
    return query(t[now].l,l,mid,x);
  else
    return query(t[now].r,mid + 1,r,x);
}//询问操作,其实写出来一看,大致操作都和线段树很像

int main(){
  int n,m;
  scanf("%d%d",&n,&m);
  for(int i = 1;i <= n;i++)
    scanf("%d",&a[i]);
  root[0] = build(0,1,n);
  for(int i = 1;i <= m;i++){
    int rt,op,x,y;
    scanf("%d%d%d",&rt,&op,&x);
    if(op == 1){
      scanf("%d",&y);
      root[i] = modify(root[rt],1,n,x,y);
    }
    else{
      printf("%d\n",query(root[rt],1,n,x));
      root[i] = root[rt];
    }
  }
  return 0;
}
主席树

明天期中啦

无论是谁都要加油啊

要考好 要继续走下去

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2019-05-07 21:28  ./seven  阅读(188)  评论(0编辑  收藏  举报