zoukankan      html  css  js  c++  java
  • BZOJ 1012 最大数

        很明显,这是道水题。尽管一开始我还不大相信,在想用什么数据结构才比较好,想过队列,当然线段树肯定也想过了。不过一直在怀疑这题有那么简单吗?不会有坑吧!事实证明没什么坑,可以跳了。最不爽的要数我在网上看到的一个题解,用单调队列写的,就开了两个数组,20行代码搞定了(只跑了400多毫秒)。我一开始写的线段树跑了900多毫秒。无意间,在看别人的博客时,看到了zkw线段树,这一神奇的东西,便学了一下。今晚zkw线段树写完了,才开始写这一博客。其实lrj在白书线段树那一块曾说过线段树有一种自底向上的写法,速度比递归的写法快,大概就是指zkw线段树了。加油。

    接下来,是最令我感慨的单调队列的代码。

     1 #include<cstdio>
     2 int m,d,a[200001] = {0},t,max[200001] = {0},l=0,p;
     3 char q[1];
     4 int main()
     5 {
     6     scanf("%d%d", &m, &d);
     7     while (m--)
     8     {
     9         scanf("%s%d",q,&p);
    10         if(q[0]=='A')
    11         {
    12             a[++t]=(l+p)%d;
    13             for(int i=t;i;i--)
    14                 if(max[i]<a[t])max[i]=a[t];
    15                 else break;
    16         }
    17         else printf("%d
    ",l=max[t-p+1]);
    18     }
    19     return 0;
    20 }

    接下来,还有我在网上看到的一个单调栈

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstdio>
     5 using namespace std;
     6 int n,d,t;
     7 int top,len,a[200001],num[200001];
     8 int main()
     9 {
    10     int x;char ch[1];
    11     scanf("%d%d",&n,&d);
    12     while(n--)
    13     {
    14               scanf("%s%d",ch,&x);
    15               if(ch[0]=='A')
    16               {
    17                       x=(x+t)%d;
    18                       num[++len]=x;
    19                       while(top&&num[a[top]]<=x)top--;
    20                       a[++top]=len;      
    21                       }
    22               else{
    23                   int y=lower_bound(a+1,a+top+1,len-x+1)-a;
    24                   t=num[a[y]];
    25                   printf("%d
    ",t=num[a[y]]);
    26               }
    27           }
    28     return 0;
    29 }

    最后就是zkw线段树了。(重点)(其实这种写法也要比自上而下的容易写)。

     1 #include<cstdio>
     2 #include<iostream>
     3 using namespace std;
     4 int num[1<<19|1] = {0};
     5 int po = (1<<18)-1;
     6  
     7 void update(int pos,int key)
     8 {
     9     pos += po;
    10     for(num[pos] = key, pos>>=1; pos; pos>>=1){
    11         num[pos] = max(num[pos<<1],num[pos<<1|1]);
    12     }
    13 }
    14  
    15 int query(int l,int r)
    16 {
    17     int ans = 0;
    18     for(l = po+l-1, r = po+r+1; l^r^1; l >>= 1, r >>= 1){
    19         if( !(l&1) ) ans = max(ans,num[l^1]);
    20         if( r & 1 ) ans = max(ans,num[r^1]);
    21     }
    22     return ans;
    23 }
    24  
    25 int main()
    26 {
    27     int m, d, x, ans = 0, cnt = 0; char c[5];
    28     scanf("%d %d", &m,&d); 
    29     while( m-- ){
    30         scanf("%s %d", c,&x);
    31         if( c[0] == 'A' ){
    32             update(++cnt,(x+ans)%d);
    33         }
    34         else {
    35             printf("%d
    ",ans=query(cnt-x+1,cnt));
    36         }
    37     }
    38     return 0;
    39 }

    1012: [JSOI2008]最大数maxnumber

    Time Limit: 3 Sec  Memory Limit: 162 MB
    Submit: 6668  Solved: 2865
    [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如上文中所述,满足(0

    Output

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

    Sample Input

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

    Sample Output

    96
    93
    96

    HINT

    人一我十,人十我万!追逐青春的梦想,怀着自信的心,永不放弃!仿佛已看到希望,尽管还在远方
  • 相关阅读:
    全文检索(SOLR)前端应用浅析续 Rails前端分析
    全文搜索应用 企业搜索SearchBlox
    持续集成(CI) 几种测试的区别(摘录)
    图解全文检索SOLR的酷应用[Ajax Solr]
    Php如何实现下载功能超详细流程分析
    在MySQL字段中使用逗号分隔符
    session的垃圾回收机制
    【转】apache常用配置
    深入理解PHP之数组(遍历顺序)
    正则表达式的子模式详解
  • 原文地址:https://www.cnblogs.com/83131yyl/p/5074130.html
Copyright © 2011-2022 走看看