洛谷 P1198 [JSOI2008]最大数

现在请求你维护一个数列(初始数列为空),要求提供以下两种操作:

1、 查询操作。

功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。

2、 插入操作。

功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。

如何每一次在末尾插入一个数并维护最大值

因为一共有\(M\)次操作,所以最多也只有可能\(M\)个数,那么当插入第\(Q\)个数时我们就把它放在第\(Q\)个位置,这样子就解决了插入操作。

查询也是很简单的,之前我们把每个数放在了末尾,现在放在了前面,所以每次只要查询从最后一个有数的位置往前\(L\)个位置,也就是\([Q-L+1,Q]\)

这样这道题就变成了一道单点修改区间和的板子题辣~!

完整代码

#include <iostream>
using namespace std;
char ch;
int ma[8000001],ad[8000001],m,d,t,q,n;
int build(int k,int l,int r)
{
    if (l==r)
    {
        ma[k]=0;
        return 0;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
}
int insert(int k,int l,int r,int x,int v)
{
    if (l==r)return ma[k]=v;
    int mid=l+r>>1;
    if (x<=mid)insert(k<<1,l,mid,x,v);
    else insert(k<<1|1,mid+1,r,x,v);
    ma[k]=max(ma[k<<1],ma[k<<1|1]);
}
int que(int k,int l,int r,int x,int y)
{
    if (l>=x&&r<=y)return ma[k];
    int mid=l+r>>1,ans=0;
    if (x<=mid)ans=max(ans,que(k<<1,l,mid,x,y));
    if (y>mid)ans=max(ans,que(k<<1|1,mid+1,r,x,y));
    ma[k]=max(ma[k<<1],ma[k<<1|1]);
    return ans;
}
int main()
{
    cin>>m>>d;
    int a1;
    n=m;
    //build(1,1,n);
    for (int i=1;i<=m;i++)
    {
        cin>>ch>>a1;
        if (ch=='A')
        {
            q++;
            insert(1,1,n,q,(a1+t)%d);
        }
        else
        {
            t=que(1,1,n,q-a1+1,q);
            cout<<t<<endl;
        }
    }
    return 0;
} 

代码丑见谅qwq

posted @ 2020-06-08 20:07  eee_hoho  阅读(76)  评论(0)    收藏  举报