zoukankan      html  css  js  c++  java
  • 【Cf #291 B】R2D2 and Droid Army(二分,线段树)

    因为题目中要求使连续死亡的机器人最多,令人联想到二分答案。

    考虑如何检验这之中是否存在一段连续的长度为md的区间,其中花最多k步使得它们都死亡。

    这个条件等价于区间中m个最大值的和不超过k。

    枚举起点,可以用 $ O(mlogn) $ 的时间确定这段区间是否合法,最终check的复杂度是 $ O(nmlogn) $。

    总复杂度是 $ O(nmlog^{2}n) $。

    $ igodot $ 技巧&套路:

    • 最大(小)值的问题,可以考虑二分答案。
    • check时用线段树优化区间平移,来枚举每一个长度固定的区间。
     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 
     5 const int N = 100005;
     6 
     7 int n, m, k, re;
     8 int a[N][6], ans[6], tmp[6];
     9 
    10 namespace SE {
    11   int ma[6][N << 2];
    12   inline void Up(int t) {
    13     for (int i = 1; i <= m; ++i) {
    14       ma[i][t] = std::max(ma[i][t << 1], ma[i][t << 1 | 1]);
    15     }
    16   }
    17   void Build(int t, int l, int r) {
    18     if (l == r) {
    19       for (int i = 1; i <= m; ++i) ma[i][t] = a[l][i];
    20       return;
    21     }
    22     int md = (l + r) >> 1;
    23     Build(t << 1, l, md);
    24     Build(t << 1 | 1, md + 1, r);
    25     Up(t);
    26   }
    27   int Query(int t, int l, int r, int L, int R, int ty) {
    28     if (L <= l && r <= R) return ma[ty][t];
    29     int md = (l + r) >> 1, re = 0;
    30     if (L <= md) re = std::max(re, Query(t << 1, l, md, L, R, ty));
    31     if (md < R) re = std::max(re, Query(t << 1 | 1, md + 1, r, L, R, ty));
    32     return re;
    33   } 
    34 }
    35 
    36 inline int Check(int md) {
    37   for (int i = 1; i + md - 1 <= n; ++i) {
    38     int sum = 0;
    39     for (int j = 1; j <= m; ++j) {
    40       tmp[j] = SE::Query(1, 1, n, i, i + md - 1, j);
    41       sum += tmp[j];
    42       if (sum > k) break;
    43     }
    44     if (sum <= k) {
    45       for (int j = 1; j <= m; ++j) ans[j] = tmp[j];
    46       return 1;
    47     }
    48   }
    49   return 0;
    50 }
    51 
    52 int main() {
    53   scanf("%d%d%d", &n, &m, &k);
    54   for (int i = 1; i <= n; ++i) {
    55     for (int j = 1; j <= m; ++j) {
    56       scanf("%d", &a[i][j]);
    57     }
    58   }
    59   SE::Build(1, 1, n);
    60   for (int nl = 1, nr = n, md; nl <= nr; ) {
    61     md = (nl + nr) >> 1;
    62     if (Check(md)) {
    63       re = md; nl = md + 1;
    64     } else {
    65       nr = md - 1;
    66     }
    67   }
    68   if (re) Check(re);
    69   for (int i = 1; i <= m; ++i) {
    70     printf("%d ", (re)? ans[i] : 0);
    71   }
    72 
    73   return 0;
    74 }
    View Code
  • 相关阅读:
    二层、三层、四层交换机的区别
    在origin 中任意设定X坐标值
    Eclipse 配置 ONE 仿真环境
    ns3 安装
    sprintf 函数
    transition属性实现hover渐变动画效果
    Mybatis处理oracle的clob类型
    Mybatis模糊查询(like)
    java.lang.OutOfMemoryError: PermGen space错误
    ORA-28000: the account is locked-的解决办法
  • 原文地址:https://www.cnblogs.com/Dance-Of-Faith/p/9296797.html
Copyright © 2011-2022 走看看