bzoj1012: [JSOI2008]最大数maxnumber(线段树)

14 篇文章 0 订阅

题目传送门
这道题是线段树的一个重要的题型吧(并不清楚重不重要)
要求最后L个数的最大值并不难。
但是他的数是一个一个插进来的。
第一次遇到这种问题可能会蒙蔽。。

首先先建一棵空树就行了。
每次插入的数就相当于在那个位置修改一下值就行。
然后求一求最大值。。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
struct node {
    int l,r,lc,rc;
    ll c;
}tr[610000];int len;
void bt(int l,int r) {
    int now=++len;
    tr[now].l=l;tr[now].r=r;
    tr[now].lc=tr[now].rc=-1;tr[now].c=0;
    if(l<r) {
        int mid=(l+r)/2;
        tr[now].lc=len+1;bt(l,mid);
        tr[now].rc=len+1;bt(mid+1,r);
    }
}
void change(int now,int x,ll k) {
    if(tr[now].l==tr[now].r) {
        tr[now].c=k;return ;
    }
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(x<=mid)
        change(lc,x,k);
    else
        change(rc,x,k);
    tr[now].c=max(tr[lc].c,tr[rc].c);
}
ll findmax(int now,int l,int r) {
    if(tr[now].l==l&&tr[now].r==r)
        return tr[now].c;
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(r<=mid)
        return findmax(lc,l,r);
    else if(l>mid)
        return findmax(rc,l,r);
    else
        return max(findmax(lc,l,mid),findmax(rc,mid+1,r));
}
int main() {
    int n;ll mod;
    scanf("%d%lld",&n,&mod);
    ll t=0;
    len=0;bt(1,200000);int trlen=0; //一开始先建一棵空树
    for(int i=1;i<=n;i++) {
        char s[5];ll x;
        scanf("%s %lld",s+1,&x);
        if(s[1]=='A') 
            change(1,++trlen,(x+t)%mod); //每次要插进来数就在那个位置修改值就可以了
        else {
            t=findmax(1,trlen-x+1,trlen); //同理吧。
            printf("%lld\n",t);
        }
    }
    return 0;
}

线段树的强大在于支持修改,log查询。
若查询特别多的话推荐用ST表咯。
O1查询。但是不支持在线修改。
太强了orz!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值