uva 11983 - Weird Advertisement(线段树)

题目链接:uva 11983 - Weird Advertisement

题目大意:给定n个矩形,问说有多少区域的面积被覆盖k次以上。

解题思路:将每个矩形差分成两条线段,一段为添加覆盖值1,一段为减少覆盖值1,同时记录两段的高度(横坐标)。然后对纵坐标离散化建立线段树,然后对线段按照高度排序,维护整段区间中覆盖度大于K的长度,乘上高度上的范围即可。

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;
const int maxn = 30005;

#define lson(x) ((x)<<1)
#define rson(x) (((x)<<1)+1)
typedef long long ll;

int N, K, R;
vector<int> bins, arr;

struct Segment {
    int l, r, h, v;
    void set (int l, int r, int h, int v) {
        this->l = l;
        this->r = r;
        this->h = h;
        this->v = v;
    }
}seg[maxn*2];

struct Node {
    int l, r, add;
    int c[12];
    void set (int l, int r, int add) {
        this->l = l;
        this->r = r;
        this->add = add;
        memset(c, 0, sizeof(c));
    }
}node[maxn*24];

inline bool cmp (const Segment& a, const Segment& b) {
    return a.h < b.h;
}

inline int search (int v) {
    return lower_bound(bins.begin(), bins.end(), v) - bins.begin();
}

void pushup (int u) {
    memset(node[u].c, 0, sizeof(node[u].c));

    if (node[u].l == node[u].r) {
        int x = node[u].l;
        node[u].c[min(K, node[u].add)] = bins[x+1] - bins[x];
    } else {
        for (int i = 0; i <= K; i++) {
            int t = min(K, i + node[u].add);
            node[u].c[t] += node[lson(u)].c[i] + node[rson(u)].c[i];
        }
    }
}

void build_segTree (int u, int l, int r) {
    node[u].set(l, r, 0); 

    if (l == r) {
        pushup(u);
        return;
    }

    int mid = (l + r) / 2;
    build_segTree(lson(u), l, mid);
    build_segTree(rson(u), mid + 1, r);
    pushup(u);
}

void insert_segTree (int u, int l, int r, int v) {
    if (l <= node[u].l && node[u].r <= r) {
        node[u].add += v;
        pushup(u);
        return;
    }

    int mid = (node[u].l + node[u].r) / 2;
    if (l <= mid)
        insert_segTree(lson(u), l, r, v);
    if (r > mid)
        insert_segTree(rson(u), l, r, v);
    pushup(u);
}

int query_segTree (int u, int l, int r) {
    if (l <= node[u].l && node[u].r <= r)
        return node[u].c[K];

    int mid = (node[u].l + node[u].r) / 2;
    int ret = 0;
    if (l <= mid)
        ret += query_segTree(lson(u), l, r);
    if (r > mid)
        ret += query_segTree(rson(u), l, r);
    return ret;
}
void add_hash (int x) {
    if (x)
        arr.push_back(x-1);
    arr.push_back(x);
    arr.push_back(x+1);
}

void init () {
    int x1, y1, x2, y2;
    arr.clear();
    scanf("%d%d", &N, &K);
    for (int i = 0; i < N; i++) {
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        seg[lson(i)].set(x1, x2, y1, 1);
        seg[rson(i)].set(x1, x2, y2+1, -1);

        add_hash(x1);
        add_hash(x2);
    }
    sort(arr.begin(), arr.end());

    bins.clear();
    bins.push_back(arr[0]);
    for (int i = 1; i < arr.size(); i++) {
        if (arr[i] != arr[i-1])
            bins.push_back(arr[i]);
    }

    R = bins.size() - 2;

    build_segTree (1, 0, R);
}

ll solve () {
    sort(seg, seg + 2 * N, cmp);

    ll ret = 0;
    for (int i = 0; i < 2 * N - 1; i++) {
        insert_segTree(1, search(seg[i].l), search(seg[i].r), seg[i].v);
        ll tmp = query_segTree(1, 0, R);
        ret += tmp * (seg[i+1].h - seg[i].h);
    }
    return ret;
}

int main () {
    int cas;
    scanf("%d", &cas);
    for (int kcas = 1; kcas <= cas; kcas++) {
        init();
        printf("Case %d: %lld\n", kcas, solve());
    }
    return 0;
}

你可能感兴趣的:(uva 11983 - Weird Advertisement(线段树))