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

来源:互联网 发布:jquery.loading.js 编辑:程序博客网 时间:2024/05/16 07:02

题目传送门
这道题是线段树的一个重要的题型吧(并不清楚重不重要)
要求最后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!!!

阅读全文
0 0
原创粉丝点击