bzoj1012 最大数

  线段树大法好,直接查后面L个数的最大值。

#include<cstdio>
#include<cctype>
#define lc o*2
#define rc o*2+1
#define mid (l+r)/2
inline int max(int x,int y){return x>y? x:y;}
inline int read(){
    char c; while(!isdigit(c=getchar())); int x=c-‘0‘;
    while(isdigit(c=getchar())) x=x*10+c-‘0‘; return x;
}
int MOD,maxv[2000001],a[2000001];
inline void maintain(int o,int l,int r){
    if(l==r) maxv[o]=a[l];
    if(l<r) maxv[o]=max(maxv[o*2],maxv[o*2+1]);
}
int l0,r0,maxx;
void update(int o,int l,int r,int x){
    if(l==r) a[l]=x;
    else {
        if(l0<=mid) update(lc,l,mid,x);
        if(r0>mid) update(rc,mid+1,r,x);
    }
    maintain(o,l,r);
}
void query(int o,int l,int r){
    if(l>=l0 && r<=r0) maxx=max(maxv[o],maxx);
    else {
        if(l0<=mid) query(lc,l,mid);
        if(r0>mid) query(rc,mid+1,r);
    }
}
int pre=0;
int main(){
    int n=read(); MOD=read(); int m=0;
    for(int i=1;i<=n;i+=1){
        char c; while(c=getchar(),c!=‘Q‘ && c!=‘A‘);
        if(c==‘A‘) l0=r0=++m,update(1,1,n,((long long)read()+pre)%MOD);
        if(c==‘Q‘) l0=m-read()+1,r0=m,maxx=-2e9,query(1,1,n),printf("%d\n",pre=maxx);
    }
    return 0;
}

  其实既然是查后面L个数,那直接倍增就行了,倍增天生支持末尾插入。

  f[i][j]表示[i,i+2^j-1]的最大值。

#include<cstdio>
#include<cmath>
inline int read(){
    char c; while(c=getchar(),c<‘0‘ || c>‘9‘); int x=c-‘0‘;
    while(c=getchar(),c>=‘0‘ && c<=‘9‘) x=x*10+c-‘0‘; return x;
}
inline int max(int x,int y){return x>y? x:y;}
int m,d,cnt,t,f[200001][18];
int main(){
    for(m=read(),d=read();m;m--){
        char c; while(c=getchar(),c!=‘A‘ && c!=‘Q‘);
        if(c==‘A‘){
            f[++cnt][0]=(long long)(read()+t)%d;
            for(int i=1;(1<<i)<=cnt;i+=1)
                f[cnt-(1<<i)+1][i]=max(f[cnt-(1<<i)+1][i-1],f[cnt-(1<<i-1)+1][i-1]);
        }else {
            int k=read(),x=log(k)/log(2);
            printf("%d\n",t=max(f[cnt-k+1][x],f[cnt-(1<<x)+1][x]));
        }
    }
    return 0;
}

  网上最多的应该是单调栈+二分的做法,和倍增一样非常好写。

  如果一个数,它后面出现一个比它大的数,那么这个数就没有意义了。于是维护一个从栈顶到栈底单调递增的栈。查询时用二分查从栈顶到栈底最多能拿到哪个。

#include<cstdio>
inline int read(){
    char c; while(c=getchar(),c<‘0‘ || c>‘9‘); int x=c-‘0‘;
    while(c=getchar(),c>=‘0‘ && c<=‘9‘) x=x*10+c-‘0‘; return x;
}
struct num{
    int x,y;
}stack[200001];
int pre=0,MOD;
inline int seek(int l,int r,int x){
    while(l<=r){
        int mid=l+r>>1;
        if(stack[mid].y<x) l=mid+1; else r=mid-1;
    }return l;
}
int main(){
    int n=read(),size=0; MOD=read();
    int m=0;
    for(int i=1;i<=n;i+=1){
        char c; while(c=getchar(),c!=‘Q‘ && c!=‘A‘);
        int x=read();
        if(c==‘A‘){
            x=((long long)x+pre)%MOD; ++m;
            while(size && x>stack[size].x) size--;
            stack[++size].x=x; stack[size].y=m;
        }else{
            pre=stack[seek(1,size,m-x+1)].x,printf("%d\n",pre);
        }
    }
}
时间: 2024-08-05 15:24:43

bzoj1012 最大数的相关文章

Bzoj1012 最大数maxnumber

Time Limit: 3000MS   Memory Limit: 165888KB   64bit IO Format: %lld & %llu Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得

bzoj1012 最大数maxnumber(线段树)

题意: Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L 个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插入操作.语法:A n 功能:将n加 上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取 模,将所得答案插入到数列的末尾.限制:n是非负整数并且在长整范围内.注意:初始时数列是空的,没有一个 数. Input 第一行两个整数,M和D,其

[单调队列]BZOJ1012 最大数maxnumber

题面 Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾.限制:n是非负整数并且在长整范围内.注意:初始时数列是空的,没有一个数. Input 第一行两个整数,M和D,其中M表示操

[JSOI2008][BZOJ1012] 最大数(动态开点线段树)

题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制:L不超过当前数列的长度. 2. 插入操作. 语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾. 限制:n是整数(可能为负数)并且在长整范围内. 注意:初始时数列是空的,没有一个数. 输入输出格式 输入格式: 第一行两个整数,M

BZOJ1012最大数maxnumber

题目 Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度. 2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾.限制:n是非负整数并且在长整范围内.注意:初始时数列是空的,没有一个数. Input 第一行两个整数,M和D,其中M表

bzoj1012最大数maxnumber——单调栈

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1012 单调栈水题:用了一下lower_bound二分. 代码如下: #include<iostream> #include<cstdio> #include<algorithm> using namespace std; int m,d,len,a[200005],sta[200005],top,lst; char s[5]; int main() { scanf

bzoj1016 SCOI2008 最大数Maxnumber

题意: 有一个序列,首先有两种操作:①查找后L个数中最大数:②[(最近一次查询得到的答案 + 常数R) % 常数D] 得到一个新数插入到序列的末尾,如果序列中没有数,那么用 0 代替 最近一次查询得到的答案. 题解:一个数插入到序列中,查询时她会影响到前面比它小的数:也就是说一个新数插入,那么这个数前面的比它小的数将没有贡献.所以想到单调队列作为此题的核心算法. CODE: /* Author: JDD PROG: bzoj1012 最大数 DATE: 2015.9.22 */ #include

bzoj-1012 1012: [JSOI2008]最大数maxnumber(线段树)

题目链接: 1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得

[BZOJ1012] [JSOI2008] 最大数maxnumber (ST表)

Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾.限制:n是非负整数并且在长整范围内.注意:初始时数列是空的,没有一个数. Input 第一行两个整数,M和D,其中M表示操作的个