这道题需要解决的是区间求值和单点修改,可以用线段树求解,首先构造一颗[1,m]的“空树”(序列至多有m个数),即每个节点维护的信息均为0,新建一个变量sum表示序列中实际数的个数,每次修改第sum个节点,最后n个数就是[sum-n+1,sum],简单维护即可。
下面给出参考代码:
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 struct node 5 { 6 int l,r,maxn; 7 }tree[800008]; 8 int m,d,n,t,sum; 9 char q; 10 void build(int k,int l,int r) 11 { 12 tree[k].maxn=-21374404;tree[k].l=l;tree[k].r=r; 13 if(l==r)return; 14 int mid=(l+r)/2; 15 build(k*2,l,mid); 16 build(k*2+1,mid+1,r); 17 } 18 void add(int k,int l,int r) 19 { 20 int ll=tree[k].l,rr=tree[k].r; 21 if(ll==rr) 22 { 23 tree[k].maxn=n; 24 return; 25 } 26 int mid=(ll+rr)/2; 27 if(sum<=mid)add(k*2,l,r); 28 else add(k*2+1,l,r); 29 tree[k].maxn=max(tree[k*2].maxn,tree[k*2+1].maxn)%d; 30 } 31 int query(int k,int l,int r) 32 { 33 int ll=tree[k].l,rr=tree[k].r; 34 if(ll>=l&&rr<=r) 35 { 36 return tree[k].maxn; 37 } 38 int mid=(ll+rr)/2; 39 int lc=-123456,rc=-123456; 40 if(sum-n+1<=mid)lc=query(k*2,l,r); 41 if(sum>mid)rc=query(k*2+1,l,r); 42 return max(lc,rc)%d; 43 } 44 void check(int l,int r,int k) 45 { 46 if(l==r) 47 { 48 cout<<tree[k].maxn<<" "; 49 return; 50 } 51 int mid=(l+r)/2; 52 check(l,mid,k*2); 53 check(mid+1,r,k*2+1); 54 return; 55 } 56 int main() 57 { 58 cin>>m>>d; 59 build(1,1,m); 60 for(int i=1;i<=m;i++) 61 { 62 cin>>q>>n; 63 if(q=='A') 64 { 65 n+=t; 66 n%=d; 67 sum++; 68 add(1,1,sum); 69 } 70 else 71 { 72 t=query(1,sum-n+1,sum)%d; 73 cout<<t<<endl; 74 } 75 } 76 return 0; 77 }