1012: [JSOI2008]最大数maxnumber
思路:
发现总的区间长度是不固定的,线段树是无法每次增加一个位置的,所以直接开始时默认区间长度是n(最多插入n个数),所以直接建线段树维护即可。
另一种思路:维护一个单调栈,从上往下保证递增,并且记录栈中每个元素的位置,每次询问寻找栈中最靠下的,位置满足条件的元素。
代码
线段树:992ms
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 7 using namespace std; 8 const int N = 800100; 9 10 int mx[N]; 11 12 #define lson l,mid,rt<<1 13 #define rson mid+1,r,rt<<1|1 14 void pushup(int rt) { 15 mx[rt] = max(mx[rt<<1],mx[rt<<1|1]); 16 } 17 void update(int l,int r,int rt,int p,int x) { 18 if (l==r) { 19 mx[rt] = x; 20 return ; 21 } 22 int mid = (l + r) / 2; 23 if (p <= mid) update(lson,p,x); 24 else update(rson,p,x); 25 pushup(rt); 26 } 27 int query(int l,int r,int rt,int L,int R) { 28 if (L <= l && r <= R) { 29 return mx[rt]; 30 } 31 int mid = (l + r) / 2,ans = -1e9; 32 if (L <= mid) ans = max(ans,query(lson,L,R)); 33 if (R > mid) ans = max(ans,query(rson,L,R)); 34 return ans; 35 } 36 int main () { 37 int n,D,a,ans = 0,cur = 0; 38 scanf("%d%d",&n,&D); 39 char s[10]; 40 for (int i=1; i<=n; ++i) { 41 scanf("%s%d",s,&a); 42 if (s[0] == 'A') { 43 a = (a + ans) % D; 44 ++cur; 45 update(1,n,1,cur,a); 46 } else { 47 ans = query(1,n,1,cur-a+1,cur); 48 printf("%d\n",ans); 49 } 50 } 51 return 0; 52 }
单调栈:1752ms
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 7 using namespace std; 8 const int N = 200100; 9 10 int st[N],top,pos[N]; 11 12 void Insert(int p,int x) { 13 while (x > st[top] && top >= 1) top--; 14 st[++top] = x; 15 pos[top] = p; 16 } 17 int Query(int p) { 18 int cur = top; 19 while (pos[cur] >= p) cur--; 20 return st[cur+1]; 21 } 22 23 int main () { 24 int n,D,a,ans = 0,cur = 0; 25 scanf("%d%d",&n,&D); 26 char s[10]; 27 for (int i=1; i<=n; ++i) { 28 scanf("%s%d",s,&a); 29 if (s[0] == 'A') { 30 a = (a + ans) % D; 31 ++cur; 32 Insert(cur,a); 33 } else { 34 ans = Query(cur-a+1); 35 printf("%d\n",ans); 36 } 37 } 38 return 0; 39 }