[JSOI2008]最大数
思路:
本题可以转化成一个线段树问题。总的操作(修改、查询)不超过M次,说明修改的次数一定≤M。因此我们可以建一棵大小为M的线段树。修改操作即为单点修改,查询操作可以转化成区间最大值,则本题实质上就是单点修改、区间最值的线段树。
1 #include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 200000 6 #define root 1 7 #define _left <<1 8 #define _right <<1|1 9 char x; 10 int m,d,t=0,y,k=0; 11 inline char getupper() { 12 register char ch; 13 while(!isupper(ch=getchar())); 14 return ch; 15 } 16 inline int getint() { 17 register char ch; 18 while(!isdigit(ch=getchar())); 19 register int x=ch-'0'; 20 while(isdigit(ch=getchar())) x=x*10+ch-'0'; 21 return x; 22 } 23 struct SegmentTree { 24 int val[maxn<<2]; 25 void initialize() { 26 for(int i=1;i<=m<<1;i++) val[i]=-0x80000000; 27 } 28 void push_up(const int p) { 29 val[p]=std::max(val[p _left],val[p _right]); 30 } 31 void modify(const int p,const int b,const int e,const int x,const int d) { 32 if(b==e) { 33 val[p]=d; 34 return; 35 } 36 int mid=(b+e)>>1; 37 if(x<=mid) { 38 modify(p _left,b,mid,x,d); 39 } 40 else { 41 modify(p _right,mid+1,e,x,d); 42 } 43 push_up(p); 44 } 45 int query(const int p,const int b,const int e,const int l,const int r) { 46 if((b==l)&&(e==r)) return val[p]; 47 int max=-0x80000000,mid=(b+e)>>1; 48 if(l<=mid) max=std::max(max,query(p _left,b,mid,l,std::min(mid,r))); 49 if(r>mid) max=std::max(max,query(p _right,mid+1,e,std::max(mid+1,l),r)); 50 return max; 51 } 52 }; 53 SegmentTree tree; 54 int main() { 55 scanf("%d%d",&m,&d); 56 tree.initialize(); 57 for(int i=1;i<=m;i++) { 58 x=getupper(); 59 y=getint(); 60 if(x=='Q') { 61 printf("%d\n",t=tree.query(root,1,m,k-y+1,k)); 62 } 63 else { 64 tree.modify(root,1,m,++k,(y+t)%d); 65 } 66 } 67 return 0; 68 }