zoukankan      html  css  js  c++  java
  • Edu73 F Choose a Square (线段树)

    题意

    在平面上有 (n) 个点, 已知每个点的 ((x, y)) 及其权值 (c),现要求在直线 (y = x) 上选择正方形的左下角与右上角,使得正方形(含边界)所覆盖点的权值和 与 边长的差值最大,边长可为0,求最大差值并输出可行方案。

    传送门

    思路

    既然正方形的一条对角线在 (y = x) 上,则可以在将点坐标离散化之后枚举右上角的坐标 (y) ,求 ([1, y]) 范围内区间和 - 边长的最大值及其下标。

    可以采用线段树维护差值的最大值及其下标。

    线段树使用

      假设点的权值和为 (sum) , 正方形左下角坐标为 ((x, x)) ,右上角坐标为((y, y)) ,则最终答案计算公式为 $ans = sum - (y-x) = sum + x - y $ 。

    将所有点的坐标离散化之后,线段树的叶子结点初值赋值为对应的 (x) ,其余则为正常维护区间和的最大值及其下标,query出的最大值即为 (sum+x) ,减去所枚举的 (y) 即为对应 (ans)

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    const int maxn = 1e6+10;
    
    int n;
    int hsy[maxn<<1], pn;
    int x[maxn], y[maxn], c[maxn];
    ll mx, pos;
    vector<int> g[maxn<<1];
    
    struct node {
        int l, r, pos; ll mx, lazy;
    }tr[maxn<<2];
    
    #define lson i<<1
    #define rson i<<1|1
    
    void pushup(int i) {
        if(tr[lson].mx > tr[rson].mx) tr[i].mx = tr[lson].mx, tr[i].pos = tr[lson].pos;
        else tr[i].mx = tr[rson].mx, tr[i].pos = tr[rson].pos;
    }
    
    void pushdown(int i) {
        if(!tr[i].lazy) return;
        tr[lson].mx += tr[i].lazy;
        tr[lson].lazy += tr[i].lazy;
        tr[rson].mx += tr[i].lazy;
        tr[rson].lazy += tr[i].lazy;
        tr[i].lazy = 0;
    }
    
    void build(int l, int r, int i) {
        tr[i] = node{l, r, l, 0, 0};
        if(l == r) {
            tr[i].mx = hsy[l];
            tr[i].pos = l;
            return;
        }
        int mid = l+r >> 1;
        build(l, mid, lson);
        build(mid+1, r, rson);
        pushup(i);
    }
    
    void update(int l, int r, ll val, int i) {
        if(l <= tr[i].l && tr[i].r <=r ) {
            tr[i].mx += val;
            tr[i].lazy += val;
            return;
        }
        pushdown(i);
        int mid = tr[i].l+tr[i].r >> 1;
        if(l <= mid) update(l, r, val, lson);
        if(mid < r) update(l, r, val, rson);
        pushup(i);
    }
    
    void query(int l, int r, int i) {
        if(l <= tr[i].l && tr[i].r <= r) {
            if(tr[i].mx > mx) {
                mx = tr[i].mx;
                pos = tr[i].pos;
            }
            return;
        }
        pushdown(i);
        int mid = tr[i].l+tr[i].r>>1;
        if(l <= mid) query(l, r, lson);
        if(r > mid) query(l, r, rson);
    }
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%d%d%d", x+i, y+i, c+i);
            if(x[i] > y[i]) swap(x[i], y[i]);
            hsy[++pn] = x[i];
            hsy[++pn] = y[i];
        }
        sort(hsy+1, hsy+1+pn);
        pn = unique(hsy+1, hsy+1+pn) - hsy-1;
    
        build(1, pn, 1);
        for (int i = 1; i <= n; ++i) {
            x[i] = lower_bound(hsy+1, hsy+1+pn, x[i]) - hsy;
            y[i] = lower_bound(hsy+1, hsy+1+pn, y[i]) - hsy;
            g[y[i]].emplace_back(i);
        }
    
        ll ans = 0, ansx = 2e9, ansy = 2e9;
    
        for (int i = 1; i <= pn; ++i) {
            for (auto v: g[i])
                update(1, x[v], c[v], 1);
            mx = pos = 0;
            query(1, i, 1);
            mx -= hsy[i];
            if(mx > ans) {
                ans = mx;
                ansx = hsy[pos];
                ansy = hsy[i];
            }
        }
        printf("%lld
    %lld %lld %lld %lld
    ", ans, ansx, ansx, ansy, ansy);
        return 0;
    }
    
    
  • 相关阅读:
    使用nginx在本地查看angular打包项目
    iso与安卓遇到的问题
    Spark 常用的读取数据api
    Spark DataFrame常用API
    spark 词频统计
    spark-shell和spark-sql
    Spark中 RDD、DF、DS的区别与联系
    SparkSQL连接Hive
    spark安装 centos7
    scala安装 centos7
  • 原文地址:https://www.cnblogs.com/acerkoo/p/11561182.html
Copyright © 2011-2022 走看看