五一集训开始就没做过题了
本来还想一直颓到期中之后,并体验一波掉色,结果并没有达成
因为上信息课太过无聊也不敢在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
",query(root[rt],1,n,x));
root[i] = root[rt];
}
}
return 0;
}
明天期中啦
无论是谁都要加油啊
要考好 要继续走下去