zoukankan      html  css  js  c++  java
  • 0x03~04 前缀和与差分、二分

    A题:HNOI2003]激光炸弹

    按照蓝书上的教程做即可,注意这道题卡空间用int 而不是 long long

    int g[5010][5010];
    int main() {
        ios_base::sync_with_stdio(false), cin.tie(0);
        int N, R;
        cin >> N >> R;
        int xx = R, yy = R;
        for (int i = 1; i <= N; ++i) {
            int x, y, w;
            cin >> x >> y >> w, ++x, ++y;
            g[x][y] = w, xx = max(xx, x), yy = max(y, yy);
        }
        for (int i = 1; i <= xx; ++i)
            for (int j = 1; j <= yy; ++j)
                g[i][j] = g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1] +
                          g[i][j];  //求前缀和
        int ans = 0;
        for (int i = R; i <= xx; ++i)
            for (int j = R; j <= yy; ++j)
                //用提前算好的前缀和减去其他部分再补上多剪的那部分
                ans =
                    max(ans, g[i][j] - g[i - R][j] - g[i][j - R] + g[i - R][j - R]);
        cout << ans << "
    ";
        return 0;
    }
    

    B题:IncDec Sequence

    设 a 的差分序列为 b.

    则对区间 [l, r] 的数都加 1,就相当于 b[l]++, b[r + 1]--.

    操作分为 4 种.

    ① 2 ≤ l ≤ r ≤ n (区间修改)

    ② 1 == l ≤ r ≤ n(修改前缀)

    ③ 2 ≤ l ≤ r == n + 1 (修改后缀)

    ④ 1 == l ≤ r == n + 1 (全修改)

    其中操作 ④ 显然无用.

    操作 ① 性价比最高.

    于是可得出方案:先用操作 ① ,使得只剩下 正数 或 负数 ,剩下的用操作 ② 或 ③ 来凑.

    using ll = long long;
    int main() {
        ios_base::sync_with_stdio(false), cin.tie(0);
        int n;
        cin >> n;
        vector<ll> a(n + 1, 0), b(n + 2);
        for (int i = 1; i <= n; ++i) cin >> a[i], b[i] = a[i] - a[i - 1];
        ll p = 0, q = 0;
        for (int i = 2; i <= n; ++i) {  // 2~n的正负数和统计
            if (b[i] > 0) p += b[i];
            else if (b[i] < 0) q -= b[i];
        }
        cout << max(p, q) << "
    " << llabs(p - q) + 1 << "
    ";
        return 0;
    }
    

    C题:Tallest Cow

    差分数组,对于给出第一个区间a,b,他们之间的人肯定比他们矮,最少矮1,那么就在a+1位置-1,b位置加1,计算前缀和,a+1以及之后的都被-1了,b及以后的不变。

    重复的区间,不重复计算。

    另一种思路:先将所有的牛的高度都设为最大值 然后在输入一组数A B时 将A B之间的牛的高度都减一。

    map<pair<int, int>, bool> vis;
    int c[10010], d[10010];
    int main() {
        ios_base::sync_with_stdio(false), cin.tie(0);
        int n, p, h, m;
        cin >> n >> p >> h >> m;
        while (m--) {
            int a, b;
            cin >> a >> b;
            if (a > b) swap(a, b);
            if (vis[make_pair(a, b)]) continue; // 避免重复计算
            vis[{a, b}] = true, d[a + 1]--, d[b]++;
        }
        for (int i = 1; i <= n; ++i) {
            c[i] = c[i - 1] + d[i];
            cout << h + c[i] << "
    ";
        }
        return 0;
    }
    

    ⭐二分A题:Best Cow Fences

    二分答案,判定是否存在一个长度不小于L的子段,平均数不小于二分的值。如果把数列中的每个数都减去二分的值,就转换为判定“是否存在一个长度不小于L的子段,子段和非负”。

    先分别考虑两种情况的解法(1、子段和最大【无长度限制】,2、子段和最大,子段长度不小于L)

    <==>求一个子段,使得它的和最大,且子段的长度不小于L。

    子段和可以转换为前缀和相减的形式,即设(sumj)表示(Ai 到 Aj)的和,

    则有:(max{A[j+1]+A[j+2].......A[i] } ( i-j>=L ) \ = max{ sum[i] - min{ sum[j] }(0<=j<=i-L) }(L<=i<=n))

    仔细观察上面的式子可以发现,随着i的增长,j的取值范围 0~i-L 每次只会增大1。换言之,每次只会有一个新的取值进入 (min{sum_j}) 的候选集合,所以我们没必要每次循环枚举j,只需要用一个变量记录当前的最小值,每次与新的取值 sum[i-L] 取min 就可以了。

    double a[100001], b[100001], sum[100001];
    int main() {
        ios_base::sync_with_stdio(false), cin.tie(0);
        int n, L;
        cin >> n >> L;
        for (int i = 1; i <= n; ++i) cin >> a[i];
        double eps = 1e-5;
        double l = -1e6, r = 1e6;
        while (r - l > eps) {
            double mid = (l + r) / 2;
            for (int i = 1; i <= n; ++i) b[i] = a[i] - mid;
            for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + b[i];
            double ans = -1e10;
            double min_val = 1e10;
            for (int i = L; i <= n; ++i) {
                min_val = min(min_val, sum[i - L]);
                ans = max(ans, sum[i] - min_val);
            }
            if (ans >= 0)
                l = mid;
            else
                r = mid;
        }
        cout << int(r * 1000) << "
    ";
        return 0;
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    Docker部署安装FasterRunner详细教程
    Centos7.6下使用docker方法安装stf
    FasterRunner在Centos7.6服务器部署
    HttpRunnerManager接口自动化测试框架在win环境下搭建教程
    Katalon
    jsoup的一个爬虫例子
    idea怎么调成黑色页面
    Idea创建一个web项目
    渗透测试基本流程
    家装流程
  • 原文地址:https://www.cnblogs.com/RioTian/p/14352048.html
Copyright © 2011-2022 走看看