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;
    }
    
    
  • 相关阅读:
    Eclipse 导入项目乱码问题(中文乱码)
    sql中视图视图的作用
    Java基础-super关键字与this关键字
    Android LayoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot)的参数理解
    Android View和ViewGroup
    工厂方法模式(java 设计模式)
    设计模式(java) 单例模式 单例类
    eclipse乱码解决方法
    No resource found that matches the given name 'Theme.AppCompat.Light 的完美解决方案
    【转】使用 Eclipse 调试 Java 程序的 10 个技巧
  • 原文地址:https://www.cnblogs.com/acerkoo/p/11561182.html
Copyright © 2011-2022 走看看