P1198 [JSOI2008]最大数

P1198 [JSOI2008]最大数

题目链接:https://www.luogu.org/problemnew/show/P1198

关键字:动态维护区间最大值

解决这道题的方法有很多种:树状数组,线段树, RMQ, 分块

树状数组:

#include<bits/stdc++.h>
using namespace std;
#define ll long long


///树状数组

const int maxn = 200000 + 50;
int m,mod;
int c[maxn];
int lowbit(int x){return -x&x;}
int Query(int x,int y)
{
    int ans=0;
    while(x<=y)
    {
        ans=max(c[y],ans);
        y--;
        for (;y-lowbit(y)>=x;y-=lowbit(y))
        {
            ans=max(c[y],ans);
        }
    }
    return ans;
}
void Update(int i, int v)
{
    while(i > 0){
        c[i] = max(c[i], v);
        i -= lowbit(i);
    }
}
char s[5]; int x;
int last = 0;
int n = 1;

int main()
{
    //freopen("DATA.c", "r", stdin);
    scanf("%d%d", &m, &mod);
    for(int i = 0; i < m; i ++){
        scanf("%s%d", s, &x);
        if(s[0] == 'A'){
            Update(n, (last+x) %mod);
            n++;
        }
        else{
            last = Query(n-x,n) % mod;
            printf("%d\n", last);
        }
    }
    return 0;
}

线段树:

#include<bits/stdc++.h>
using namespace std;
#define ll long long


///线段树

const int INF =  0x80000000;
const int maxn = 200000 + 50;
int m,mod;
char s[5]; int x;
int last = 0;
int n = 0;

struct Node
{
    int l;
    int r;
    int val;
}segTree[maxn<<2];

void Build(int i, int l, int r)
{
    segTree[i].l = l;
    segTree[i].r = r;
    segTree[i].val = INF;
    if(l == r) {
        return ;
    }
    int mid = l + r >> 1;
    Build(i<<1, l,mid);
    Build(i<<1|1, mid+1,r);
}

void Update(int i, int pos, int val)
{
    if(segTree[i].l == pos && segTree[i].r == pos){
        segTree[i].val = val; return ;
    }
    int mid = segTree[i].l + segTree[i].r >> 1;
    if(pos <= mid) Update(i<<1,pos,val);
    else if(pos > mid) Update(i<<1|1,pos,val);
    segTree[i].val = max(segTree[i<<1].val, segTree[i<<1|1].val);
}

int Query(int i, int l, int r)
{
    if(segTree[i].l == l && segTree[i].r == r){
        return segTree[i].val;
    }
    int mid = segTree[i].l + segTree[i].r >> 1;
    if(r <= mid) return Query(i<<1,l,r);
    else if(l > mid) return Query(i<<1|1,l,r);
    else{
        return max(Query(i<<1,l,mid), Query(i<<1|1, mid+1,r));
    }
}

int main()
{
   //freopen("DATA.c", "r", stdin);
    scanf("%d%d", &m, &mod);
    Build(1,1,m);
    for(int i = 0; i < m; i ++){
        scanf("%s%d", s, &x);
        if(s[0] == 'A'){
            Update(1,++n,(x+last)%mod);
        }
        else{
            last = Query(1,n-x+1,m) % mod;
            printf("%d\n", last);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值