BZOJ 1012 线段树或单调栈

来源:互联网 发布:学大数据要什么基础 编辑:程序博客网 时间:2024/05/22 07:44

线段树的话很显然了,插入,询问,注意建的数的大小就好M的4倍就够了。

#include <bits/stdc++.h>#define INF 0x7fffffffusing namespace std;struct data{int l,r,mx;}t[800005];int M,D,last,cnt;void build(int k,int l,int r){    t[k].l=l;t[k].r=r;t[k].mx=-INF;    if(l==r)return;    int mid=(l+r)>>1;    build(k<<1,l,mid);    build(k<<1|1,mid+1,r);}int ask(int k,int x,int y){    int l=t[k].l,r=t[k].r;    if(l==x&&r==y)return t[k].mx;    int mid=(l+r)>>1;    if(y<=mid)return ask(k<<1,x,y);    else if(x>mid)return ask(k<<1|1,x,y);    else return max(ask(k<<1,x,mid),ask(k<<1|1,mid+1,y));}void in(int k,int d,int v){    int l=t[k].l,r=t[k].r;    if(l==r){        t[k].mx=v;return ;    }    int mid=(l+r)>>1;    if(d<=mid)in(k<<1,d,v);    else in(k<<1|1,d,v);    t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);}int main(){    scanf("%d%d",&M,&D);    cnt=0;    last=0;    int tmp;    build(1,1,M);    while(M--){        char s[5];        scanf("%s",s);        if(s[0]=='A'){           scanf("%d",&tmp);           tmp=(last+tmp)%D;           in(1,++cnt,tmp);        }        else {            scanf("%d",&tmp);            printf("%d\n",last=ask(1,cnt-tmp+1,cnt));        }    }    return 0;}

然后注意到因为是询问后L个数中的最大值,所以当一个数插入到末尾时比前面的都大,则前面的数显然不是答案,所以可以直接弹出(比这个数小的弹出,所以是个递减的单调栈),然后询问时二分查找L这一位置即可,栈内存的是位置。

#include <bits/stdc++.h>#define INF 0x7fffffffusing namespace std;int M,D,L,R,last,x,cnt;int q[200005];int a[200005];char s[5];int main(){    R=-1;    scanf("%d%d",&M,&D);    while(M--){        scanf("%s",s);        if(s[0]=='A'){          scanf("%d",&x);          x=(x+last)%D;          a[++cnt]=x;          while(L<=R&&a[q[R]]<=x)R--;          q[++R]=cnt;        }        else {            scanf("%d",&x);            int d=*lower_bound(q,q+R+1,cnt-x+1);            last=a[d];            printf("%d\n",last);        }    }    return 0;}
0 0
原创粉丝点击