1012: [JSOI2008]最大数maxnumber
Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 5572 Solved: 2424
[ 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如上文中所述,满足(0
Output
对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。
Sample Input
5 100
A 96
Q 1
A 97
Q 1
Q 2
A 96
Q 1
A 97
Q 1
Q 2
Sample Output
96
93
96
93
96
思路:
查询区间内的最大值,并且M又有200000这么大,所以要用线段树。开始没仔细考虑数据大小,我用单链表写。。自然超时了
代码:
//这是单链表写的,超时
#include<iostream>
#include<cstring>
using namespace std;
#define LIST_NUM 200000
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
void InitList(LinkList &L)
{
L=new LNode;
L->next=NULL;
}
void CreatList(LinkList L,ElemType e)
{
LNode *p;
p=new LNode;
if(L->next==NULL){
L->next=p;
p->next=NULL;
}
else{
p->next=L->next;
L->next=p;
}
p->data=e;
}
void ShowList(LinkList L)
{
LNode *s=L->next;
while(s)
{
cout<<s->data<<" ";
s=s->next;
}
cout<<endl;
}
int main()
{
LNode *L;
InitList(L);
ElemType e[LIST_NUM];
int M,D;
char ask;
cin>>M>>D;
int num;
int en;
int flag=0;
for(int i=1;i<=M;i++)
{
cin>>ask>>num;
if(ask=='A')
{
if(flag==0)
en=0;
int t=num+en;
t=t%D;
CreatList(L,t);
}
else if(ask=='Q')
{
LNode *s=L->next;
int maxn=0;
while(num--)
{
if(s->data>maxn)
maxn=s->data;
s=s->next;
}
cout<<maxn<<endl;
en=maxn;
if(flag==0)
flag=1;
}
}
return 0;
}
//线段树写的,AC
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 200005
int n,mod,last;
int big[maxn<<2];
void Pushup(int rt)
{
big[rt] = max(big[rt<<1],big[rt<<1|1]);
}
void updata(int L,int num,int l,int r,int rt)
{
if(l==r)
{
big[rt] = num;
return;
}
int m = (l+r)>>1;
if(L<=m)
updata(L,num,lson);
else
updata(L,num,rson);
Pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l && R>=r)
return big[rt];
int m = (l+r)>>1;
int ret = 0;
if(L<=m)
ret = max(ret,query(L,R,lson));
if(R > m)
ret = max(ret,query(L,R,rson));
return ret;
}
int main()
{
char op[5];
cin>>n>>mod;
last = 0;
int k,len=0;
for(int i=0;i<n;i++)
{
scanf("%s%d",op,&k);
if(op[0]=='A')
{
++len;
updata(len,(k+last)%mod,1,n,1);
}
else
printf("%d\n",last=query(len-k+1,len,1,n,1));
}
return 0;
}
下面两个是HZWER博客上看到的。。智商压制。。
//单调栈
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdio>
int n,d,t;
int top,len,a[200001],num[200001];
int main()
{
int x;char ch[1];
scanf("%d%d",&n,&d);
while(n--)
{
scanf("%s%d",ch,&x);
if(ch[0]=='A')
{
x=(x+t)%d;
num[++len]=x;
while(top&&num[a[top]]<=x)top--;
a[++top]=len;
}
else{
int y=lower_bound(a+1,a+top+1,len-x+1)-a;
t=num[a[y]];
printf("%d\n",t=num[a[y]]);
}
}
return 0;
}
//单调队列:
#include<cstdio>
int m,d,a[200001],t,max[200001],l=0,p;
char q[1];
int main()
{
scanf("%d%d", &m, &d);
while (m--)
{
scanf("%s%d",q,&p);
if(q[0]=='A')
{
a[++t]=(l+p)%d;
for(int i=t;i;i--)
if(max[i]<a[t])max[i]=a[t];
else break;
}
else printf("%d\n",l=max[t-p+1]);
}
return 0;
}