• P1198 [JSOI2008]最大数


    P1198 [JSOI2008]最大数

    2017-09-04


    Description

    现在请求你维护一个数列,要求提供以下两种操作: 1、 查询操作。语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。 2、 插入操作。语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个数。


    Input

    第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0


    Output

    对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。


    Sample Input

    5 100
    A 96
    Q 1
    A 97
    Q 1
    Q 2

    Sample Output

    96
    93
    96

    bz的神机子,我不想再看到它.....
    线段树维护区间最大值,每一次插入一个数就相当于单点修改,每一次修改都是log m,时间复杂度m*log m,就是这个在线很烦啊...
    注意线段树边界,因为会有负数,所以不能简单的tr[k]=max(tr[k<<1],tr[k<<1|1])想想为什么...反正这是一边过的...
    再也不用scanf读入字符了....
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int read(){
        char ch=getchar();
        int an=0,f=1;
        while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-f;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    int D,M;
    struct saber{
    int l,r,Ma;
    }tr[200000*4+99];
    void build(int k,int l,int r){
        int mid=(l+r)>>1;
        tr[k].l=l;tr[k].r=r;
        if(l==r)return;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    void add(int k,int shu,int data){
        int l=tr[k].l,r=tr[k].r;
        int mid=(l+r)>>1;
        if(l==r&&l==shu){tr[k].Ma=data;return;}
        if(shu<=mid){add(k<<1,shu,data);}
        else add(k<<1|1,shu,data);
        tr[k].Ma=max(tr[k].Ma,data);
    }
    int ask(int k,int i,int j){
        int l=tr[k].l,r=tr[k].r;
        if(l==i&&r==j){return tr[k].Ma;}
        int mid=(l+r)>>1;
        if(mid>=j){return ask(k<<1,i,j);}
        else if(i>mid){return ask(k<<1|1,i,j);}
        else return max(ask(k<<1,i,mid),ask(k<<1|1,mid+1,j));
    }
    char c;int x;
    int re,tot;
    int main(){
        M=read();D=read();
        build(1,1,M);
        for(int i=1;i<=M;i++){
        cin>>c;x=read();
        if(c=='Q'){re=ask(1,tot+1-x,tot);printf("%d
    ",re);}
        else {tot++;add(1,tot,(re+x)%D);}
        }
        return 0;
    }
    线段树
    反正一颗线段树不加懒标签最多10分钟...很好打的..x

    by:s_a_b_e_r


    表示楼上线段树dalao……写线段树各种错的我qwq
    看着旁边s开始敲线段树,我默默的开始写树状数组
    求区间最值这种事,树状数组还是能做到的
    安利一发讲树状数组的博客
     
    树状数组区间最值求法就是从这学来的
    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int N=200099;
    int m,d,a[N],c[N],t,len;
    int lowbit(int x){return x&(-x);}
    int found(int l,int r)
    {
        int ans=0;
        while (r>=l)
        {
            ans=max(a[r],ans);--r;
            for(;r-lowbit(r)>=l;r-=lowbit(r))
                ans=max(c[r],ans);
        }
        return ans;
    }
    void add(int k,int x)
    {
         while(k<=N)
         {
           c[k]=max(c[k],x);
           k+=lowbit(k);
         }
    }
    int main()
    {
        scanf("%d%d",&m,&d);
        for(int i=1;i<=m;++i)
        {
          char x;int y;
          cin>>x>>y;
          if(x=='Q')
          {
            t=found(len-y+1,len);
            printf("%d
    ",t);
          }
          else if(x=='A')
          {
            y=(y+t)%d;
            a[++len]=y;
            add(len,a[len]);
          }
        }
        return 0;
    }
    maxnumber

    表示bz有毒……最近各种迷之RE

    以及据说这题单调队列单调栈都可以解决……?


    s:我不想到bz交题了QAQ.....
    w:+1,bz有毒qwq
  • 相关阅读:
    学习Java书籍推荐和面试网站推荐
    Java 多线程学习扩展
    Java Excel 导入导出(二)
    Java Excel 导入导出(一)
    Matplotlib库(二)
    Matplotlib库(一)
    【转】MATLAB导出精美的论文插图
    图像的手绘效果
    Numpy库的使用(二)
    Numpy库的使用(一)
  • 原文地址:https://www.cnblogs.com/ck666/p/7473949.html
Copyright © 2020-2023  润新知