《进阶指南》练习0x03、0x04

0x03

0x03练习网址

这三个题都是前缀和/差分,跟递归半毛钱关系都没有。

A

P2280 [HNOI2003]激光炸弹

二维前缀和裸题。

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

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;
}
posted @ 2021-04-10 13:03  Theophania  阅读(116)  评论(0)    收藏  举报