zoukankan      html  css  js  c++  java
  • BZOJ_1012_[JSOI2008]_最大数maxnumber_(线段树/树状数组+RMQ)

    描述


    http://www.lydsy.com/JudgeOnline/problem.php?id=1012

    两种操作:

    1.求序列末尾n个数中的最大值.

    2.在序列末尾插入一个数.

    分析


    线段树求RMQ裸题,不离线也可以做.

    我们来说说怎么用树状数组求RMQ.

    求区间和值的树状数组中c[i]表示的是区间(i-lowbit(i)+1,c[i])的和值,我们现在让它表示这个区间的最大值.

    1.查询操作get_max(l,r).

    如果l<=r-lowbit(r)+1.那么c[r]表示的区间全部在(l,r)内部,于是就ret=max(ret,c[r]),r-=lowbit(r).

    否则,ret=max(ret,num[r]),r--.

    2.插入操作.update(id,x).

    求出区间M=(id-lowbit(id),id)的最大值,c[id]=max(M,num[id]).

    这样只会用到查询操作,画图可知,每次查询"上去","下来"最多是2logn,所以复杂度是(O(logn))的.

    线段树:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=200000+5;
     5 struct node{
     6     int l,r,m;
     7 }a[maxn<<2];
     8 int m,d,t,n,cnt;
     9 char str[3];
    10 void build(int l,int r,int k){
    11     a[k].l=l; a[k].r=r;
    12     if(l==r) return;
    13     int mid=l+(r-l)/2;
    14     build(l,mid,k<<1); build(mid+1,r,k<<1|1);
    15 }
    16 void update(int id,int x,int k){
    17     if(a[k].l==a[k].r){
    18         a[k].m=x;
    19         return;
    20     }
    21     int mid=a[k].l+(a[k].r-a[k].l)/2;
    22     if(id<=mid) update(id,x,k<<1);
    23     else update(id,x,k<<1|1);
    24     a[k].m=max(a[k<<1].m,a[k<<1|1].m);
    25 }
    26 int get_max(int l,int r,int k){
    27     if(a[k].l==l&&a[k].r==r) return a[k].m;
    28     int mid=a[k].l+(a[k].r-a[k].l)/2;
    29     if(r<=mid) return get_max(l,r,k<<1);
    30     else if(l>mid) return get_max(l,r,k<<1|1);
    31     else return max(get_max(l,mid,k<<1),get_max(mid+1,r,k<<1|1));
    32 }
    33 int main(){
    34     scanf("%d%d",&m,&d);
    35     build(1,m,1);
    36     while(m--){
    37         scanf("%s%d",str,&n);
    38         if(str[0]=='A'){
    39             cnt++;
    40             update(cnt,(t+n)%d,1);
    41         }
    42         else printf("%d
    ",t=get_max(cnt-n+1,cnt,1));
    43     }
    44     return 0;
    45 }
    View Code

    树状数组:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=200000+5;
     5 int m,d,n,t,cnt;
     6 int a[maxn],c[maxn];
     7 char str[3];
     8 inline int lowbit(int x){ return x&-x; }
     9 int get_max(int l,int r){
    10     if(r<l) return 0;
    11     int ret=a[r];
    12     while(l<=r){
    13         if(r-lowbit(r)+1>=l){
    14             ret=max(ret,c[r]);
    15             r-=lowbit(r);
    16         }
    17         else ret=max(ret,a[r]), r--;
    18     }
    19     return ret;
    20 }
    21 int main(){
    22     scanf("%d%d",&m,&d);
    23     while(m--){
    24         scanf("%s%d",str,&n);
    25         if(str[0]=='A'){
    26             a[++cnt]=(n+t)%d;
    27             c[cnt]=max(get_max(cnt-lowbit(cnt)+1,cnt-1),a[cnt]);
    28         }
    29         else{
    30             printf("%d
    ",t=get_max(cnt-n+1,cnt));
    31         }
    32     }
    33     return 0;
    34 }
    View Code

    1012: [JSOI2008]最大数maxnumber

    Time Limit: 3 Sec  Memory Limit: 162 MB
    Submit: 7678  Solved: 3313
    [Submit][Status][Discuss]

    Description

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

    Input

      第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足D在longint内。接下来
    M行,查询操作或者插入操作。

    Output

      对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。

    Sample Input

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

    Sample Output

    96
    93
    96

    HINT

      数据如下http://pan.baidu.com/s/1i4JxCH3

    Source

  • 相关阅读:
    javascript 编码规范
    javascript 减少全部变量
    轮播图 jquery
    SVN MAC
    php excel
    php email
    查看网站后台
    linux 下载文件
    第6周小组作业:软件测试和评估
    第4周小组作业:WordCount优化
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5579682.html
Copyright © 2011-2022 走看看