Educational Codeforces Round 73 (Rated for Div. 2) DF题解

还想小号上分来着,结果F题翻车,最后两分钟才绝杀F,导致水题没切,上分变上坟了

D Make The Fence Great Again

题意:有n个木板,每个木头都有高度和提升一个单位高度的花费,一个木头可以多次提升高度,要求相邻木头高度不能相同,求最少总花费。
解法:因为只是要求相邻木头不能等高,所以每个木头最多只用升两次高度就行,那我们设 d [ i ] [ j ] d[i][j] 为前 i i 个木头合法且第 i i 个木头升了 j j 次高度的最小花费,我们对于第 i 1 i-1 个木头,枚举其升级次数 j j ,枚举第 i i 个木头,枚举升级次数 k k ,显然 d [ i ] [ k ] = m i n ( d [ i ] [ k ] , d [ i 1 ] [ j ] + k b [ i ] ) d[i][k]=min(d[i][k], d[i-1][j]+k*b[i])
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 3e5 + 10;
ll d[maxn][3], inf = 1e18;
int a[maxn], b[maxn];
void up(ll &x, ll y) {
    x = min(x, y);
}
ll solve() {
    int n;
    scanf("%d", &n);
    scanf("%d%d", &a[1], &b[1]);
    d[1][1] = b[1];
    d[1][2] = 2ll * b[1];
    for (int i = 2; i <= n; i++) {
        scanf("%d%d", &a[i], &b[i]);
        d[i][0] = d[i][1] = d[i][2] = inf;
        for (int j = 0; j < 3; j++)
        for (int k = 0; k < 3; k++)
            if (a[i] + j != a[i - 1] + k)
                up(d[i][j], d[i - 1][k] + j * b[i]);
    }
    ll ans = inf;
    for (int i = 0; i < 2; i++)
        up(ans, d[n][i]);
    return ans;
}
int main() {
    int T;
    scanf("%d", &T);
    while (T--)
        printf("%lld\n", solve());
}

F. Choose a Square

题意:给出一些平面内带权值的点,现在要你选择一个正方形,要求正方形的正对角线和 y = x y=x 重合,然后定义正方形权值:方形内所有点权之和 - 正方形边长,求出权值最大的正方形
解法:我们可以把所有点投影到 y = x y=x 上排个序,假设顺着 y = x y=x 走到了 x = i x=i ,定义 r [ j ] r[j] 为矩形 ( 0 , 0 ) ( i , j ) (0, 0)(i,j) 内的所有点总权值, c [ j ] c[j] 为矩形 ( 0 , 0 ) ( j , i ) (0,0)(j,i) 内的所有点总权值,设 S [ j ] S[j] 为矩形 ( 0 , 0 ) ( j , j ) (0,0)(j,j) 的总权值,设 d [ i ] d[i] 为固定右上角为 ( i , i ) (i,i) 时所能得到的正方形的最大的权值,我们枚举正方形左下端点 ( j , j ) (j,j) 容斥一下下:
d [ i ] = m a x ( d [ i ] , S [ j 1 ] + r [ i ] r [ j 1 ] + c [ i ] c [ j 1 ] S [ i ] ( i j ) ) d[i]=max(d[i], S[j-1]+r[i]-r[j-1]+c[i]-c[j-1]-S[i]-(i-j)) ,去掉一些常量化简一下:
d [ i ] = m a x ( S [ j 1 ] r [ j 1 ] c [ j 1 ] + j ) d[i]=max(S[j-1]-r[j-1]-c[j-1]+j) ,这一步可能很多大佬都能一眼看出来了,直接线段树维护 S [ j ] r [ j ] c [ j ] + j + 1 S[j]-r[j]-c[j]+j+1 的最大值即可,离散化一下下就so easy咯
#include<bits/stdc++.h>
#define ll long long
#define ls o * 2
#define rs o * 2 + 1
#define mid (l + r) / 2
using namespace std;
const int maxn = 1e6 + 1;
ll inf = 1e18;
int X[maxn];
vector<int> G[maxn];
struct seg {
    int pos;
    ll mx, tag;
    seg operator+(const seg& t) const {
        seg tmp;
        tmp.mx = max(mx, t.mx);
        if (mx >= t.mx)
            tmp.pos = pos;
        else
            tmp.pos = t.pos;
        return tmp;
    }
} tree[maxn * 4];
void build(int o, int l, int r) {
    if (l == r) {
        tree[o].pos = l;
        tree[o].tag = tree[o].mx = 0;
        return;
    }
    build(ls, l, mid);
    build(rs, mid + 1, r);
    tree[o] = tree[ls] + tree[rs];
}
void pushdown(int o) {
    if (tree[o].tag) {
        ll tag = tree[o].tag;
        tree[ls].tag += tag;
        tree[rs].tag += tag;
        tree[ls].mx += tag;
        tree[rs].mx += tag;
        tree[o].tag = 0;
    }
}
void up(int o, int l, int r, int ql, int qr, ll v) {
    if (l >= ql && r <= qr) {
        tree[o].mx += v;
        tree[o].tag += v;
        return;
    }
    pushdown(o);
    if (ql <= mid)
        up(ls, l, mid, ql, qr, v);
    if (qr > mid)
        up(rs, mid + 1, r, ql, qr, v);
    tree[o] = tree[ls] + tree[rs];
}
seg qu(int o, int l, int r, int ql, int qr) {
    if (l >= ql && r <= qr)
        return tree[o];
    pushdown(o);
    if (qr <= mid)
        return qu(ls, l, mid, ql, qr);
    else if (ql > mid)
        return qu(rs, mid + 1, r, ql, qr);
    else return qu(ls, l, mid, ql, qr) + qu(rs, mid + 1, r, ql, qr);
}
int x[maxn], y[maxn], w[maxn];
int main() {
    int n, sz = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d", &x[i], &y[i], &w[i]);
        X[++sz] = x[i];
        X[++sz] = y[i];
    }
    sort(X + 1, X + 1 + sz);
    sz = unique(X + 1, X + 1 + sz) - X - 1;
    for (int i = 1; i <= n; i++) {
        x[i] = lower_bound(X + 1, X + 1 + sz, x[i]) - X;
        y[i] = lower_bound(X + 1, X + 1 + sz, y[i]) - X;
        G[max(x[i], y[i])].push_back(i);
    }
    build(1, 1, sz);
    ll ans = 0, cat = 0;
    int x1 = 2e9, x2 = 2e9;
    for (int i = 1; i <= sz; i++) {
        for (auto id : G[i]) {
            cat += w[id];
            int k = max(x[id], y[id]);
            up(1, 1, sz, k, sz, w[id]);
            up(1, 1, sz, x[id], sz, -w[id]);
            up(1, 1, sz, y[id], sz, -w[id]);
        }
        if (i != 1) {
            seg tmp = qu(1, 1, sz, 1, i - 1);
            ll res = tmp.mx + cat - X[i];
            if (res > ans) {
                ans = res;
                x1 = X[tmp.pos + 1];
                x2 = X[i];
            }
        }
        if (cat - (X[i] - X[1]) > ans) {
            ans = cat - (X[i] - X[1]);
            x1 = X[1];
            x2 = X[i];
        }
        up(1, 1, sz, i, i, X[i + 1]);
    }
    printf("%lld\n%d %d %d %d", ans, x1, x1, x2, x2);
}
发布了302 篇原创文章 · 获赞 98 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/ccsu_cat/article/details/101042538