E - Cloudy Day 鲨臂做法之线段树

题目: https://vjudge.z180.cn/contest/423156#problem/E
题意:一条线上,有房子,房子上边可能有云彩,现在可以把一片云彩轰掉,求把房子之中的人口数在没有云彩的数量最大。
解析: 用坐标维护一个线段树,用区间更新来更新没有云彩的人口,注意开longlong

代码:

#include <bits/stdc++.h>
#define lowbit(x) x&(-x)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const ll llINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
const double DINF = 1e20;
const double eps = 1e-7;
const double PI = acos(-1.0);
const int mod = 1e9 + 7;
const int N = 8e5 + 50;

int n, m, p[N], x[N], y[N], r[N];
vector<int > sct;

struct node
{
    
    
    int l, r; ll cnt, c;
} tr[N * 4];
inline void Build(int l, int r, int root)
{
    
    
    tr[root] = {
    
    l, r};
    if (l == r) return ;
    int mid = l + r >> 1;
    Build(l, mid, root << 1), Build(mid + 1, r, root << 1 | 1);
}

inline void Push_up(int root)
{
    
    
    if (tr[root].c == 0) {
    
    
        tr[root].cnt = tr[root << 1].cnt + tr[root << 1 | 1].cnt;
    } else tr[root].cnt = 0;
}

inline void Insert(int root, int idx, int val)
{
    
    
    if (tr[root].l == tr[root].r) {
    
    
        tr[root].cnt += val;
        return ;
    }
    int mid = tr[root].l + tr[root].r >> 1;
    if (idx <= mid) Insert(root << 1, idx, val);
    else Insert(root << 1 | 1, idx, val);
    Push_up(root);
}

inline void Push_down(int root)
{
    
    
    tr[root << 1].c = tr[root << 1 | 1].c = tr[root].c;
}

inline void Modify(int root, int L, int R, int val)
{
    
    
    if (tr[root].l >= L && tr[root].r <= R) {
    
    
        tr[root].c += val;
        Push_up(root);
        return ;
    }
    int mid = tr[root].l + tr[root].r >> 1;
    if (L <= mid) Modify(root << 1, L, R, val);
    if (R > mid) Modify(root << 1 | 1, L, R, val);
    Push_up(root);
}

inline int Get(int x)
{
    
    
    return lower_bound(sct.begin(), sct.end(), x) - sct.begin();
}

int main()
{
    
    
    //ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

    scanf("%d", &n);

    for (int i = 1; i <= n; i++) scanf("%d", &p[i]);

    for (int i = 1; i <= n; i++) {
    
    
        scanf("%d", &x[i]);
        sct.push_back(x[i]);
    }

    scanf("%d", &m);
    for (int i = 1; i <= m; i++) scanf("%d", &y[i]);

    for (int i = 1; i <= m; i++) {
    
    
        scanf("%d", &r[i]);
        sct.push_back(y[i] - r[i]), sct.push_back(y[i] + r[i]);
    }

    sort(sct.begin(), sct.end());
    sct.erase(unique(sct.begin(), sct.end()), sct.end());

    int len = sct.size();

    Build(0, len - 1, 1);

    for (int i = 1; i <= n; i++) {
    
    
        Insert(1, Get(x[i]), p[i]);
    }

    ll ans = 0;

    for (int i = 1; i <= m; i++) {
    
    
        Modify(1, Get(y[i] - r[i]), Get(y[i] + r[i]), 1);
    }

    for (int i = 1; i <= m; i++) {
    
    
        Modify(1, Get(y[i] - r[i]), Get(y[i] + r[i]), -1);
        ans = max(ans, tr[1].cnt);
        Modify(1, Get(y[i] - r[i]), Get(y[i] + r[i]), 1);
    }

    printf("%lld\n", ans);

    return 0;
}

Guess you like

Origin blog.csdn.net/YingShen_xyz/article/details/113831817