《进阶指南》练习0x03、0x04
0x03
这三个题都是前缀和/差分,跟递归半毛钱关系都没有。
A
二维前缀和裸题。
const int maxn = 5e3 + 9;
int s[maxn][maxn];
signed main()
{
int n, m;
read(n, m);
for (int i = 1; i <= n; ++i)
{
int x, y, v;
read(x, y, v);
s[x + 1][y + 1] = v;
}
for (int i = 1; i < maxn; ++i)
for (int j = 1; j < maxn; ++j)
s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
int ans = 0;
for (int i = m; i < maxn; ++i)
for (int j = m; j < maxn; ++j)
ans = max(ans, s[i][j] - s[i - m][j] - s[i][j - m] + s[i - m][j - m]);
cout << ans << endl;
return 0;
}
B
P4552 [Poetize6] IncDec Sequence
区间加相当于在差分数组上左边加右边减,目标是差分数组第二项开始全为 \(0\)。那么第一问就做完了。
第二问是这样的:对于差分数组中配完对剩下的的正数或负数,选择区间加或减都是自由的,各自会给答案增加一种情况。
代码:
int a[maxn], d[maxn];
signed main()
{
int n;
read(n);
for (int i = 1; i <= n; ++i)
{
read(a[i]);
d[i] = a[i] - a[i - 1];
}
ll cnt1 = 0, cnt2 = 0;
for (int i = 2; i <= n; ++i)
{
if (d[i] > 0)
cnt1 += d[i];
else
cnt2 -= d[i];
}
cout << max(cnt1, cnt2) << endl;
cout << abs(cnt1 - cnt2) + 1 << endl;
return 0;
}
C
P2879 [USACO07JAN]Tallest Cow S
这题去年做过,就不写代码了。自己构造差分数组,对于每个给出的区间 \([l,r]\),d[l+1]--, d[r]++,最后求一遍前缀和即可。区间注意判重。
0x04
只有一个题 #10012. 「一本通 1.2 例 2」Best Cow Fences
二分平均值即可。
const double eps = 1e-8;
const int maxn = 1e5 + 9;
int n, L;
double a[maxn], s[maxn];
bool check(double avg) {
for (int i = 1; i <= n; ++i)
s[i] = s[i - 1] + a[i] - avg;
double mins = 1e10;
for (int i = L; i <= n; ++i) {
mins = min(mins, s[i - L]);
if (s[i] > mins)
return true;
}
return false;
}
signed main() {
cin >> n >> L;
for (int i = 1; i <= n; ++i)
cin >> a[i];
double l = *min_element(a + 1, a + n + 1);
double r = *max_element(a + 1, a + n + 1);
while (r - l > eps) {
double mid = (l + r) / 2;
if (check(mid))
l = mid;
else
r = mid;
}
cout << (int)(r * 1000) << endl;
return 0;
}

浙公网安备 33010602011771号