洛谷 P1198 [JSOI2008]最大数——单调栈/线段树

先上一波题目 https://www.luogu.org/problem/P1198

题目要求维护后缀最大值 以及在数列的最后面添加一个数

这道题呢我们有两种做法

1.单调栈 

因为只需要维护后缀最大值 而我们每次插入都是在最后面添加一个数 所以我们可以维护一个单调栈

栈底到栈顶逐渐增大 因为如果一个数他的位置在你的前面且他比你小 那么他便不会对前面位置的最大值产生影响 可以直接省略

我们在查询的时候只需要二分一下答案 找到比查询位置后的最接近查询位置的数的值就是答案了

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=200007;
long long  read(){
    long long ans=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
}
char c;
int stk[M],top=0;
int n,cnt=0;
long long mod,s[M],T=0,x;
int main(){
    n=read(); mod=read();
    for(int i=1;i<=n;i++){
        c=getchar();  
        while(c!='Q'&&c!='A') c=getchar();
        x=read();
        if(c=='Q'){
            x=cnt-x+1;
            long long l=1,r=top;
            while(l<r){
                int mid=(l+r)>>1; 
                if(stk[mid]>=x) r=mid;
                else l=mid+1;
            }
            T=s[r];
            printf("%lld\n",T);
        }
        else{
            cnt++;
            x=(x+T)%mod;
            x=(x+mod)%mod; 
            while(top&&s[top]<=x) top--;
            s[++top]=x; stk[top]=cnt;
        }
    }
    return 0;
}
View Code

2.线段树

线段树就很明显了 设计的操作有单点插入 区间求最大值

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=400007;
long long  read(){
    long long ans=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
}
char c;
int n,cnt=0;
long long mod,T=0,now,s[M*2];
void up(int x){s[x]=max(s[x<<1],s[x<<1^1]);}
void insert(int x,int l,int r){
    if(l==r){
        s[x]=now;
        return ;
    }
    int mid=(l+r)>>1;
    if(cnt<=mid) insert(x<<1,l,mid);
    else insert(x<<1^1,mid+1,r);
    up(x);
}
long long pmx(int x,int l,int r){
    if(now<=l&&r<=cnt) return s[x];
    int mid=(l+r)>>1;
    long long ans=-2147483647;
    if(now<=mid) ans=max(ans,pmx(x<<1,l,mid));
    if(cnt>mid)  ans=max(ans,pmx(x<<1^1,mid+1,r));
    return ans;
}
int main(){
    n=read(); mod=read();
    for(int i=1;i<=n;i++){
        c=getchar();
        while(c!='Q'&&c!='A') c=getchar();
        now=read();
        if(c=='Q'){
            now=cnt-now+1;
            T=pmx(1,1,n);
            printf("%lld\n",T);
        }
        else{
            cnt++;
            now=(now+T)%mod;
            insert(1,1,n);
        }
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/yourinA/p/11651010.html
今日推荐