• uva 12393 Nonnegative Partial Sums 【单调队列】


    后来看了07年周泽(大概是?)的论文,才知道原来这个是一个很经典的单调队列题。

    题意:给出一个长度为n序列,每次将第一个元素移至最后可以得到有n种序列,问其中有多少个满足对于所以的i(1≤i≤n),sigma(a[k]),(1≤k≤i)>=0,就是可以维护一个递增的序列,这样每次取队首就O(1)的求出是否满足条件了,维护序列只需要O(n)的复杂度。

    比赛的时候用dp思想的st(rmq)的O(nlogn)的算法超时了,后来知道原来有一种RMQ转换为LCA,又转化为RMQ的算法可以做,这样复杂度也可要跟单调队列的做法一样,转换为O(n)。

    这类单调队列的基本做法吧。

    比较习惯的写法:

    l=0; r=-1;

    for(k=0;k<=n;k++){

      while(l<=r&&(没有更优的判断条件,直接带入r计算即可)) r--;

      q[++r] = k;

      /*if(判断是否有符合题目的解) ans++;(类似的)

      while(对于l的边界条件,下一次的l不符合判断条件) l++;*/

      或者

      while(对于l的边界条件,此次l不符合判断条件) l++;

      if(判断是否有符合题目的解) ans++;(类似的)

      

    }

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<map>
     7 #define see(x) cout<<#x<<":"<<x<<endl;
     8 using namespace std;
     9 const int maxn = 1000005;
    10 int a[maxn], sum[maxn<<1], que[maxn<<1];
    11 int main(){
    12     int n, i, j, k, s, ans, l, r;
    13     while(~scanf("%d",&n)&&n){
    14         scanf("%d",&a[0]);
    15         sum[0] = a[0];
    16         for(i=1;i<n;i++){
    17             scanf("%d",&a[i]);
    18             sum[i] = sum[i-1]+a[i];
    19         }
    20         for(i=n;i<2*n;i++){
    21             sum[i] = sum[i-1]+a[i-n];
    22         }
    23         ans = 0;
    24         l = r = 0;
    25         for(i=0;i<2*n;i++){
    26             while(l<r&&sum[i]<sum[que[r-1]]) r--;
    27             que[r++] = i;
    28             if(i>=n&&sum[que[l]]-sum[i-n]>=0) ans++;
    29             while(l<r&&que[l]<=i-n+1) l++;
    30         }
    31         printf("%d\n",ans);
    32     }
    33     return 0;
    34 }
  • 相关阅读:
    用户交互
    python简介
    maven阿里云镜像setting
    apache虚拟主机的ip用法 包括iis
    apache的虚拟主机配置和指定目录的访问描述(
    apache重定向301 配置,根域名转到www
    前端学习
    一步一步写jQuery插件
    json 和 table控件
    下载相关
  • 原文地址:https://www.cnblogs.com/celia01/p/2645747.html
Copyright © 2020-2023  润新知