zoukankan      html  css  js  c++  java
  • luogu 2629 好消息,坏消息

    题目描述

    uim在公司里面当秘书,现在有n条消息要告知老板。每条消息有一个好坏度,这会影响老板的心情。告知完一条消息后,老板的心情等于之前老板的心情加上这条消息的好坏度。最开始老板的心情是0,一旦老板心情到了0以下就会勃然大怒,炒了uim的鱿鱼。

    uim为了不被炒,知道了了这些消息(已经按时间的发生顺序进行了排列)的好坏度,希望研究如何不让老板发怒。

    uim必须按照时间的发生顺序逐条将消息告知给老板。不过uim可以使用一种叫“倒叙”的手法,例如有n条消息,小a可以从k,k+1,k+2...n,1,2...k-1这种顺序通报。

    他希望知道,有多少个k,从k开始通报到n然后从1通报到k-1可以让老板不发怒。

    输入格式

    第一行一个整数n(1 <= n <= 10^6),表示有n个消息。

    第二行n个整数,按时间顺序给出第i条消息的好坏度Ai(-1000 <= Ai <= 1000)

    输出格式

    一行一个整数,表示可行的方案个数。

    输入输出样例

    输入 #1
    4
    -3 5 1 2 
    输出 #1
    2
    

    说明/提示

    样例解释

    [5 1 2 -3]或[1 2 -3 5]

    对于25%数据n<=1000

    对于75%数据n<=10000

    对于100%数据n<=10^6

    分析

    这道题是一样的

    我们用前缀和方便求区间和

    由于是环形,开两倍

    朴素算法,每到一个点时,判断以任意点为起点时的区间和是否小于零,如果小于零,那么不能做为起点

    也就是说,每次只保留令sum[i] - sum[j] >= 0的j,到最后剩下的点就是合法起点

    也就是满足sum[j-1]<=sum[i]的点保留

    嗯?有点眼熟?、

    单调队列不就是这个操作嘛

    每次入队新值前都会弹出比他大(或小)的值以维护队列单调

    OK

    代码

     1 /**********************
     2 User:Mandy.H.Y
     3 Language:c++
     4 Problem: luogu 2629
     5 Algorithm:
     6 **********************/
     7 
     8 #include<bits/stdc++.h>
     9 
    10 using namespace std;
    11 
    12 const int maxn = 1e6 + 5;
    13 
    14 int n,ans;
    15 int a[maxn << 1];
    16 int sum[maxn << 1];
    17 int l,r,q[maxn << 1];
    18 
    19 template<class T>inline void read(T &x){
    20     x = 0;bool flag  = 0;char ch = getchar();
    21     while(! isdigit(ch)) flag |= ch == '-',ch = getchar();
    22     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
    23     if(flag) x = -x;
    24 }
    25 
    26 template<class T>void putch(const T x){
    27     if(x > 9) putch(x / 10);
    28     putchar(x % 10 | 48);
    29 }
    30 
    31 template<class T>void put(const T x){
    32     if(x < 0) putchar('-'),putch(-x);
    33     else putch(x);
    34 }
    35 
    36 void file(){
    37     freopen("2629.in","r",stdin);
    38     freopen("2629.out","w",stdout);
    39 }
    40 
    41 void readdata(){
    42     read(n);
    43     for(int i = 1;i <= n; ++ i) read(a[i]),a[i+n]=a[i];
    44     for(int i = 1;i <= n + n; ++ i) sum[i] = sum[i - 1] + a[i];
    45 }
    46 
    47 void work(){
    48     
    49     for(int i = 1;i <= n + n; ++ i){
    50         while(l < r && q[l] + n <= i ) ans++,l++;
    51         q[r++] = i;
    52         while(l < r && sum[q[r-1]-1] > sum[i]) r--;
    53         
    54     }
    55     put(ans);
    56 }
    57 
    58 int main(){
    59 //    file();
    60     readdata();
    61     work();
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    牛客练习赛64 D.宝石装箱 【容斥原理+背包DP】
    洛谷 P5212 SubString【SAM+LCT】
    洛谷 P4219 [BJOI2014]大融合【LCT】
    洛谷 P1501 [国家集训队]Tree II【LCT】
    洛谷 P5357 【模板】AC自动机(二次加强版)
    洛谷 P3690 【模板】Link Cut Tree (动态树)
    洛谷 P2463 [SDOI2008]Sandy的卡片【后缀数组】
    P3181 [HAOI2016]找相同字符【后缀数组】
    洛谷 SP705 【后缀数组】
    牛客小白月赛18 E.Forsaken的数列【Splay】
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11469411.html
Copyright © 2011-2022 走看看