• BZOJ 4385: [POI2015]Wilcze doły


    4385: [POI2015]Wilcze doły

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 648  Solved: 263
    [Submit][Status][Discuss]

    Description

    给定一个长度为n的序列,你有一次机会选中一段连续的长度不超过d的区间,将里面所有数字全部修改为0。
    请找到最长的一段连续区间,使得该区间内所有数字之和不超过p。

    Input

    第一行包含三个整数n,p,d(1<=d<=n<=2000000,0<=p<=10^16)。
    第二行包含n个正整数,依次表示序列中每个数w[i](1<=w[i]<=10^9)。

    Output

    包含一行一个正整数,即修改后能找到的最长的符合条件的区间的长度。

    Sample Input

    9 7 2
    3 4 1 9 4 1 7 1 3

    Sample Output

    5

    HINT

    将第4个和第5个数修改为0,然后可以选出区间[2,6],总和为4+1+0+0+1=6。

    Source

    [Submit][Status][Discuss]

    分析

    显然单调队列O(N)扫过去即可,就是注意优化常数。

    代码

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6  
     7 using namespace std;
     8  
     9 #define gc getchar
    10 #define add(x,y) x=x*10+y-'0'
    11  
    12 template <class T>
    13 __inline void read(T &x)
    14 {
    15     x = 0; char c = gc();
    16      
    17     while (c < '0')
    18         c = gc();
    19      
    20     while (c >= '0')add(x,c),
    21         c = gc();
    22 }
    23  
    24 #define mem(x) memset(x,0,sizeof(x))
    25 #define rep(x) for(int i=1;i<=x;++i)
    26  
    27 #define ll long long
    28 #define LL long long
    29  
    30 #define N 4000005
    31  
    32 int n;
    33 int d;
    34 int num[N];
    35 int que[N];
    36  
    37 LL p;
    38 LL sum[N];
    39 LL mex[N];
    40  
    41 signed main(void)
    42 {
    43     read(n);
    44     read(p);
    45     read(d);
    46      
    47     rep(n)read(num[i]);
    48     rep(n)sum[i] = sum[i - 1] + num[i];
    49     rep(n - d + 1)mex[i] = sum[i + d - 1] - sum[i - 1];
    50      
    51     int h = 0, t = 0, lt = 0, ans = 0;
    52      
    53     for (int i = d; i <= n; ++i)
    54     {
    55         while (h < t && mex[que[t - 1]] <= mex[i - d + 1])
    56             --t;
    57              
    58         que[t++] = i - d + 1;
    59          
    60         while (sum[i] - sum[lt] - mex[que[h]] > p)
    61         {
    62             ++lt; while (que[h] <= lt)++h;
    63         }
    64          
    65         if (i - lt > ans)ans = i - lt;
    66     }
    67      
    68     printf("%d
    ", ans);
    69 }
    BZOJ_4385.cpp
     1 #include <bits/stdc++.h>
     2 
     3 typedef long long longint;
     4 
     5 const int maxn = 4000005;
     6 
     7 int n;
     8 int d;
     9 int num[maxn];
    10 int que[maxn];
    11 
    12 longint p;
    13 longint sum[maxn];
    14 longint mex[maxn];
    15 
    16 signed main(void)
    17 {
    18     scanf("%d%lld%d", &n, &p, &d);
    19 
    20     for (int i = 1; i <= n; ++i)
    21         scanf("%d", num + i);
    22 
    23     for (int i = 1; i <= n; ++i)
    24         sum[i] = sum[i - 1] + num[i];
    25 
    26     for (int i = 1; i <= n - d + 1; ++i)
    27         mex[i] = sum[i + d - 1] - sum[i - 1];
    28 
    29     int head = 0, tail = 0, left = 0, answer = 0;
    30 
    31     for (int i = d; i <= n; ++i) {
    32         while (head < tail && mex[que[tail - 1]] <= mex[i - d + 1])
    33             --tail; // queue pop back
    34 
    35         que[tail++] = i - d + 1;
    36 
    37         while (sum[i] - sum[left] - mex[que[head]] > p) {
    38             ++left;
    39             while (que[head] <= left)
    40                 ++head; // queue pop front
    41         }
    42 
    43         if (answer < i - left)
    44             answer = i - left;
    45     }
    46 
    47     printf("%d
    ", answer);
    48 }
    BZOJ_4385.cpp

    @Author: YouSiki

  • 相关阅读:
    Java 核心编程——文件随机读写类(RandomAccessFile)
    java 核心编程——文件过滤类(FileFilter和FilenameFilter)
    java 核心编程 ——文件操作类File
    java 编程思想笔记(七)——异常
    java 编程思想笔记(六)——内部类
    enote笔记法使用范例(2)——指针(1)智能指针
    enote笔记法使用范例(1)——自己总结的一些编写代码的常识 (a)
    enote笔记语言(2)
    enote笔记语言(1)
    monkey命令——压力测试——转载参考07
  • 原文地址:https://www.cnblogs.com/yousiki/p/6091604.html
Copyright © 2020-2023  润新知