您的位置:首页 > Web前端 > JavaScript

【BZOJ 1012】【JSOI 2008】最大数maxnumber

2016-11-12 11:34 459 查看

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

题解

直接强上。

【线段树|BIT|单调栈】

SegmentTree

#include<iostream>
#include<cstdio>
using namespace std;
int M,D,last,cnt;
struct data
{
int l,r,mx;
}t[800005];
void build(int idx,int l,int r)
{
t[idx].l=l;
t[idx].r=r;
t[idx].mx=-1;
if(l==r)
return;
int mid=(l+r)>>1;
build(idx<<1,l,mid);
build(idx<<1|1,mid+1,r);
}
inline int Query(int idx,int l,int r)
{
if (t[idx].l==l&&t[idx].r==r)
return t[idx].mx;
int mid=(t[idx].l+t[idx].r)>>1;
if (r<=mid)
return Query(idx<<1,l,r);
else if (l>mid)
return  Query(idx<<1|1,l,r);
else
return max(Query(idx<<1,l,mid),Query(idx<<1|1,mid+1,r));
}

inline void insert (int idx,int i,int x)
{
if(t[idx].l==t[idx].r)
{
t[idx].mx=x;
return;
}
int mid=(t[idx].l+t[idx].r)>>1;
if (i<=mid)
insert (idx<<1,i,x);
else
insert (idx<<1|1,i,x);
t[idx].mx=max(t[idx<<1].mx,t[idx<<1|1].mx);
}

int main()
{
scanf ("%d%d",&M,&D);
build(1,1,M);
int t=0;
int j=0,x;
for (int i=1;i<=M;i++)
{
char cym[5];
scanf ("%s",cym);
if(cym[0]=='A')
{
scanf ("%d",&x);
j++;
x=(x+t)%D;
insert(1,j,x);
}
else
{
scanf ("%d",&x);
t=Query(1,j-x+1,j);
printf("%d\n",t);
}
}
return 0;
}


BIT

#include <cstdio>
using namespace std;
#define lowbit(x) (x&-x)
#define max(a,b) ((a)>(b)?(a):(b))
const int N=200005;
int num
, c
, cnt;
int getk(int l, int r) {
int ret=num[r];
while(l<=r) {
ret=max(ret, num[r]);
for(--r; r-l>=lowbit(r); r-=lowbit(r))
ret=max(ret, c[r]);
}
return ret;
}

int main() {
int n, d, t=0, a;
char ch[3];
scanf("%d%d", &n, &d);
while(n--) {
scanf("%s%d", ch, &a);
if(ch[0]=='A') {
num[++cnt]=(t+a)%d;
c[cnt]=max(getk(cnt-lowbit(cnt)+1, cnt-1), num[cnt]);
}
else {
printf("%d\n", t=getk(cnt-a+1, cnt));
}
}
return 0;
}


单调栈

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 250001
#define eps 1e-9
const int inf=0x7fffffff;   //无限大
//**************************************************************************************
int a[maxn],max_num[maxn],t=0,ans=0;
int main()
{
int n,d;
scanf("%d%d",&n,&d);
char ch[3];
int g;
while(n--)
{
scanf("%s%d",ch,&g);
if(ch[0]==‘A‘)
{
a[++t]=(ans+g)%d;
for(int i=t;i;i--)
{
if(max_num[i]<a[t])
max_num[i]=a[t];
else
break;
}
}
else
{
ans=max_num[t-g+1];
printf("%d\n",ans);
}
}
return 0;
}


单调队列

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

int n,m,last,mod;
int q[200005],id[200005],head,tail;
void add(int x)
{
while (q[tail]<=x && tail) tail--;
q[++tail]=x;id[tail]=++n;
}
int query(int x)
{
int l=n-x+1;
int k=lower_bound(id+head,id+tail+1,l)-id;
return q[k];
}
int main()
{
scanf("%d%d",&m,&mod);
char ch[2];
int x;
head=1;tail=0;
while (m--)
{
scanf("%s%d",ch,&x);
if (ch[0]=='A')
add((x+last)%mod);
else printf("%d\n",last=query(x));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  单调栈 线段树 BIT