【Codeforces #291 B】R2D2 and Droid Army

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

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

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

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

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

$ \bigodot $ 技巧&套路:

  • 最大(小)值的问题,可以考虑二分答案。
  • 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 }

原文地址:https://www.cnblogs.com/Dance-Of-Faith/p/9296797.html

时间: 2024-10-02 22:04:26

【Codeforces #291 B】R2D2 and Droid Army的相关文章

【Codeforces:从头开始】contest 1

[Codeforces:从头开始]contest 1      1A      用 a × a 的石板覆盖 n × m 的长方形广场,允许石板覆盖的区域超出广场,不允许打破石板,石板的两侧应平行于广场两侧,要求覆盖完广场所需的石板数量最少是多少 样例图示: (显然,答案为每边必须铺的+铺出去(1个或0个)) 注意开 long long 代码: #include<bits/stdc++.h> using namespace std; typedef long double ld; typedef

Codeforces #291 (Div. 2) D. R2D2 and Droid Army(RMQ+二分)

题意: 有n*m的矩阵,然后你有k发子弹.现在你可以朝着任意列发射子弹,每一发子弹都会使该列上的数值-1,最小减少到0. 现在问你连续最长的行数,在k发子弹内,使得这些行上的数值全部为0. 思路: 简单的二分枚举最长行数区间,每个区间的最大值决定了要发射的子弹数,所以是RMQ问题,当然这里的枚举全部枚举,用尺取法也可以. //889 ms #include<cstdio> #include<algorithm> #include<cstring> #include<

Codeforces 514 D R2D2 and Droid Army(RMQ+二分)

An army of n droids is lined up in one row. Each droid is described by m integers a1,?a2,?...,?am, where ai is the number of details of thei-th type in this droid's mechanism. R2-D2 wants to destroy the sequence of consecutive droids of maximum lengt

【CodeForces 353 A】Domino

[链接] 我是链接,点我呀:) [题意] [题解] 分类讨论一波 设第一个数组的奇数个数为cnt1 第二个数组的奇数个数为cnt2 显然只有在(cnt1+cnt2)%2==0的情况下. 才可能第一个数组的和为偶数,第二个数组的和也为偶数 (因为奇数都要出现偶数次才可以. 所以只可能cnt1和cnt2都是偶数,那么输出0 否则,cnt1和cnt2都是奇数,看看有没有一个位置i只有a[i]或只有b[i]是奇数.有的话输出1. 其他情况都非法. [代码] #include <bits/stdc++.h

【Codeforces Round 1129】[Alex Lopashev Thanks-Round] (Div. 1)

Codeforces Round 1129 这场模拟比赛做了\(A1\).\(A2\).\(B\).\(C\),\(Div.1\)排名40. \(A\)题是道贪心,可以考虑每一个站点是分开来的,把目的地最小编号的留到最后,所以答案稍微算一下就行了. \(B\)题是道找规律,首先可以很容易地发现只要前面弄个负数的开头,错误算法就会忽略掉这一个值,所以利用这个来构造答案.(最讨厌构造题了)然后推导一番式子就会发现如果我们将第一个值放-1,则 \(\sum_{i=2}^na_i=k+n\), 再更改一

【Codeforces Round 1132】Educational Round 61

Codeforces Round 1132 这场比赛做了\(A\).\(B\).\(C\).\(F\)四题,排名\(89\). \(A\)题\(wa\)了一次,少考虑了一种情况 \(D\)题最后做出来,但被\(hack\)了...被\(hack\)的原因是没有想到答案会超过\(10^{12}\)(毕竟这个时间上的优化也是在最后迫不得已的情况下加的,就没有考虑正确性... Codeforces 1132 C 题意:给一些区间\([l_i,r_i]\),从中删掉两个,求剩下的区间最多能够覆盖的格子数

【Codeforces Round 650】Codeforces #334 (Div. 1)

模拟CF650,ABC三题,RK90 Codeforces 650 A 思路:首先看式子 \(\sqrt{(x_i-x_j)^2+(y_i-y_j)^2}=|x_i-x_j|+|y_i-y_j|\) 的唯一可行的情况是\(x_i=x_j\)或\(y_i=y_j\).(因为两边之和大于第三边 所以就知道怎么做了. 第一种方法:我们维护三个\(map\),分别存行.列.坐标是\(\dots\)的时候已经有多少个节点. 然后就可以边读边算,读到\((x,y)\)这个坐标的时候把\(ans\)变成 \(

【Codeforces 718 A】Efim and Strange Grade

Codeforces 718 A 题意:给一个小数,问最多取\(t\)次四舍五入到某一个小数点后的位后这个数最大能到多少. 思路:首先肯定贪心.(但不知道为什么tag上是\(dp\) 首先我们找到最靠左的一个大于等于5的数,把它四舍五入到上一位, 然后再不断地往前找到下一个大于等于5的数,再四舍五入到上一位... 然后就好了. 原文地址:https://www.cnblogs.com/denverjin/p/10810469.html

【Codeforces 85 D】Sum of Medians

Codeforces 85 D 题意:维护一个有序集合,每次问编号\(mod\ 5\)余\(3\)的所有数的和. 思路:线段树维护\(mod\ 5\)余\(x\)的数的和,然后上推的时候根据左节点的值改一下就好了. Codeforces 718 A 题意:给一个小数,问最多取\(t\)次四舍五入到某一个小数点后的位后这个数最大能到多少. 思路:首先肯定贪心.(但不知道为什么tag上是\(dp\) 首先我们找到最靠左的一个大于等于5的数,把它四舍五入到上一位, 然后再不断地往前找到下一个大于等于5