1. 程式人生 > >BZOJ——1012: [JSOI2008]最大數maxnumber || 洛谷—— P1198 [JSOI2008]最大數

BZOJ——1012: [JSOI2008]最大數maxnumber || 洛谷—— P1198 [JSOI2008]最大數

geo target cin scrip page discus 一行 功能 des

http://www.lydsy.com/JudgeOnline/problem.php?id=1012||

https://www.luogu.org/problem/show?pid=1198

Time Limit: 3 Sec Memory Limit: 162 MB
Submit: 10824 Solved: 4735
[Submit][Status][Discuss]

Description

  現在請求你維護一個數列,要求提供以下兩種操作:1、 查詢操作。語法:Q L 功能:查詢當前數列中末尾L
個數中的最大的數,並輸出這個數的值。限制:L不超過當前數列的長度。2、 插入操作。語法:A n 功能:將n加

上t,其中t是最近一次查詢操作的答案(如果還未執行過查詢操作,則t=0),並將所得結果對一個固定的常數D取
模,將所得答案插入到數列的末尾。限制:n是非負整數並且在長整範圍內。註意:初始時數列是空的,沒有一個
數。

Input

  第一行兩個整數,M和D,其中M表示操作的個數(M <= 200,000),D如上文中所述,滿足D在longint內。接下來
M行,查詢操作或者插入操作。

Output

  對於每一個詢問操作,輸出一行。該行只有一個數,即序列中最後L個數的最大數。

Sample Input

5 100
A 96
Q 1
A 97
Q 1
Q 2

Sample Output

96
93
96

HINT

  數據如下http://pan.baidu.com/s/1i4JxCH3

Source

①區間查詢最值考慮線段樹、

技術分享
 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 
 7 const int N(200005);
 8 int t,mod,n,x[N],ans;
 9 char ch,s[N];
10 
11 struct Tree
12 { 13 int l,r,sum; 14 }tr[N<<2]; 15 #define lc (now<<1) 16 #define rc (now<<1|1) 17 #define mid (tr[now].l+tr[now].r>>1) 18 inline void Tree_up(int now) 19 { 20 tr[now].sum=max(tr[lc].sum,tr[rc].sum); 21 } 22 void Tree_build(int now,int l,int r) 23 { 24 tr[now].l=l; tr[now].r=r; 25 if(l==r) return ; 26 Tree_build(lc,l,mid); 27 Tree_build(rc,mid+1,r); 28 } 29 void Tree_change(int now,int to,int x) 30 { 31 if(tr[now].l==tr[now].r) 32 { 33 tr[now].sum=x; 34 return ; 35 } 36 if(to<=mid) Tree_change(lc,to,x); 37 else Tree_change(rc,to,x); 38 Tree_up(now); 39 } 40 int Tree_query(int now,int l,int r) 41 { 42 if(tr[now].l==l&&r==tr[now].r) return tr[now].sum; 43 if(r<=mid) return Tree_query(lc,l,r); 44 else if(l>mid) return Tree_query(rc,l,r); 45 else return max(Tree_query(lc,l,mid),Tree_query(rc,mid+1,r)); 46 } 47 48 int main() 49 { 50 scanf("%d%d",&t,&mod); 51 for(int i=1;i<=t;i++) 52 { 53 cin>>ch>>x[i]; s[i]=ch; 54 if(ch==A) n++; 55 } 56 Tree_build(1,1,n); 57 int cnt=0; 58 for(int i=1;i<=t;i++) 59 { 60 if(s[i]==A) 61 Tree_change(1,++cnt,(ans+x[i])%mod); 62 else 63 { 64 ans=Tree_query(1,cnt-x[i]+1,cnt); 65 printf("%d\n",ans); 66 } 67 } 68 return 0; 69 }
線段樹AC

②單調遞減棧,二分查找位於L處的值

技術分享
 1 #include <algorithm>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 
 6 const int N(200005);
 7 int n,mod,ans,x;
 8 int stack[N],top,num[N],len;
 9 
10 int main()
11 {
12     scanf("%d%d",&n,&mod);
13     for(char ch[2];n--;)
14     {
15         scanf("%s%d",ch,&x);
16         if(ch[0]==A)
17         {
18             x=(x+ans)%mod;
19             num[++len]=x;
20             for(;num[stack[top]]<=x&&stack[top]>0&&top;) top--;
21             stack[++top]=len;
22         }
23         else
24         {
25             int l=1,r=top;
26             for(int mid;l<=r;)
27             {
28                 mid=l+r>>1;
29                 if(stack[mid]<len-x+1) l=mid+1;
30                 else r=mid-1,ans=num[stack[mid]];
31             }
32             printf("%d\n",ans);
33         }
34     }
35     return 0;
36 }
單調棧AC

BZOJ——1012: [JSOI2008]最大數maxnumber || 洛谷—— P1198 [JSOI2008]最大數