水题,暴力修改都能过。
#include<bits/stdc++.h> using namespace std; const int maxn=1000010; int n,m,k,p; char flag; int a[maxn]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } for(int i=1;i<=m;i++) { cin>>flag; if(flag=='Q') { scanf("%d",&p); printf("%d ",a[p]); } else { scanf("%d%d",&k,&p); a[k]=p; } } return 0; }
查询某个版本,肯定是可持久化数据结构,单点修改,用可持久化线段树即可,每次修改时新开一条链,这样就大大减少了空间的开销。
查询某个版本,从某次操作的根节点向下查询即可。
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+7; int a[maxn]; int n,m; int cnt; struct node{ int lson,rson,val;//左儿子,右儿子,权值 }tree[maxn*4]; int root[maxn]; char opt; int x,y; int tim; void copynode(int neww,int old){ tree[neww].lson=tree[old].lson; tree[neww].rson=tree[old].rson; tree[neww].val=tree[old].val; } void build(int rt,int l,int r){ if(l==r){ tree[rt].val=a[l]; return; } tree[rt].lson=++cnt;//动态开点 tree[rt].rson=++cnt; int mid=l+r>>1; build(tree[rt].lson,l,mid); build(tree[rt].rson,mid+1,r); } void update(int rt,int l,int r,int ori,int pos,int x){ copynode(rt,ori); if(l==r){ tree[rt].val=x; return; } int mid=l+r>>1; if(pos<=mid){ tree[rt].lson=++cnt; update(tree[rt].lson,l,mid,tree[ori].lson,pos,x); } else{ tree[rt].rson=++cnt; update(tree[rt].rson,mid+1,r,tree[ori].rson,pos,x); } } int query(int rt,int l,int r,int pos){ if(l==r) return tree[rt].val; int mid=(l+r)>>1; if(pos<=mid) return query(tree[rt].lson,l,mid,pos); else return query(tree[rt].rson,mid+1,r,pos); } int main(){ scanf("%d%d",&n,&m); root[0]=++cnt; for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(root[0],1,n); while(m--){ cin>>opt>>x>>y; if(opt=='Q'){ tim++; root[tim]=root[tim-1]; printf("%d ",query(root[y],1,n,x)); } if(opt=='M'){ tim++; root[tim]=++cnt;//新开节点 update(root[tim],1,n,root[tim-1],x,y); } } return 0; }
线段树单点修改。
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+7; struct node{ int l,r; long long sum; }tree[maxn*20]; int a[maxn],n,m; int x,v,l1,r1; char opt[5]; void build(int now,int l,int r){ tree[now].l=l,tree[now].r=r; if(l==r){ tree[now].sum=a[l]; return; } int mid=(l+r)>>1; build(now<<1,l,mid); build(now<<1|1,mid+1,r); tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum; } void update(int now,int x,int v){ if(tree[now].l==tree[now].r){ tree[now].sum=v; return; } int mid=(tree[now].l+tree[now].r)>>1; if(x<=mid) update(now<<1,x,v); else update(now<<1|1,x,v); tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum; } long long query(int now,int l,int r){ if(tree[now].l>=l&&tree[now].r<=r) return tree[now].sum; long long val=0; int mid=(tree[now].l+tree[now].r)>>1; if(l<=mid) val+=query(now<<1,l,r); if(r>mid) val+=query(now<<1|1,l,r); return val; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); for(int i=1;i<=m;i++){ scanf("%s",opt); if(opt[0]=='M'){ scanf("%d%d",&x,&v); update(1,x,v); } else{ scanf("%d%d",&l1,&r1); printf("%d ",query(1,l1,r1)); } } return 0; }
线段树区间赋值。
FBI Warning:此题数据有毒,赋值时会有负的,注意lazy标记的初始化。
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+7; struct node{ int l,r; long long lazy; long long sum; }tree[maxn*25]; int n,m; long long a[maxn]; int l,r; long long v; char opt[666]; void build(int now,int l,int r){ tree[now].l=l,tree[now].r=r,tree[now].lazy=-99999999; if(l==r){ tree[now].sum=a[l]; return; } int mid=(l+r)>>1; build(now<<1,l,mid); build(now<<1|1,mid+1,r); tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum; } void pushdown(int now){ if(tree[now].lazy!=-99999999){ tree[now<<1].sum=(tree[now<<1].r-tree[now<<1].l+1)*tree[now].lazy; tree[now<<1|1].sum=(tree[now<<1|1].r-tree[now<<1|1].l+1)*tree[now].lazy; tree[now<<1].lazy=tree[now].lazy; tree[now<<1|1].lazy=tree[now].lazy; tree[now].lazy=-99999999; } } void update(int now,int l,int r,long long v){ if(tree[now].l>=l&&tree[now].r<=r){ tree[now].sum=(tree[now].r-tree[now].l+1)*v; tree[now].lazy=v; return; } pushdown(now); int mid=(tree[now].l+tree[now].r)>>1; if(l<=mid) update(now<<1,l,r,v); if(r>mid) update(now<<1|1,l,r,v); tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum; } long long query(int now,int l,int r){ if(tree[now].l>=l&&tree[now].r<=r) return tree[now].sum; pushdown(now); int mid=(tree[now].l+tree[now].r)>>1; long long val=0; if(l<=mid) val+=query(now<<1,l,r); if(r>mid) val+=query(now<<1|1,l,r); return val; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); build(1,1,n); for(int i=1;i<=m;i++){ scanf("%s",opt); if(opt[0]=='M') scanf("%d%d%lld",&l,&r,&v),update(1,l,r,v); else scanf("%d%d",&l,&r),printf("%lld ",query(1,l,r)); } return 0; }