https://www.luogu.org/problemnew/show/P3919
如题,你需要维护这样的一个长度为 N 的数组,支持如下几种操作
在某个历史版本上修改某一个位置上的值
- 访问某个历史版本上的某一位置的值
此外,每进行一次操作(对于操作2,即为生成一个完全一样的版本,不作任何改动),就会生成一个新的版本。版本编号即为当前操作的编号(从1开始编号,版本0表示初始状态数组)
这题题意看错了就很伤……操作2新建的版本是它所询问的历史版本emmm……
以及各种小错误,int没return,y打成x,以及脑子抽了加了个k++。
总之做过BZOJ3673 & BZOJ3674 & 洛谷3402:可持久化并查集之后做这道题就很简单啦。
我们开主席树记录修改和询问就ok啦。
好像题解写到这里就没了emmmm……
#include<cstdio> #include<queue> #include<cctype> #include<cstring> #include<cmath> #include<vector> #include<algorithm> using namespace std; const int N=1e6+5; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct tree{ int l,r,v; }tr[N*20]; int a[N],rt[N],n,m,pool; inline void build(int &x,int l,int r){ x=++pool; if(l==r){ tr[x].v=a[l]; return; } int mid=(l+r)>>1; build(tr[x].l,l,mid); build(tr[x].r,mid+1,r); } inline void modify(int y,int &x,int l,int r,int pos,int v){ tr[x=++pool]=tr[y]; if(l==r){ tr[x].v=v; return; } int mid=(l+r)>>1; if(pos<=mid)return modify(tr[y].l,tr[x].l,l,mid,pos,v); else modify(tr[y].r,tr[x].r,mid+1,r,pos,v); } inline int query(int x,int l,int r,int pos){ if(l==r)return tr[x].v; int mid=(l+r)>>1; if(pos<=mid)return query(tr[x].l,l,mid,pos); else return query(tr[x].r,mid+1,r,pos); } int main(){ n=read(),m=read(); for(int i=1;i<=n;i++)a[i]=read(); build(rt[0],1,n); for(int i=1;i<=m;i++){ rt[i]=rt[i-1]; int k=read(),op=read(); if(op==1){ int pos=read(),v=read(); modify(rt[k],rt[i],1,n,pos,v); } if(op==2){ int pos=read(); printf("%d ",query(rt[k],1,n,pos)); rt[i]=rt[k]; } } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++