UVA 11983 - Weird Advertisement
题意:给定几个矩形,之后,求覆盖k次以上的点
思路:先把坐标离散化掉,然后把每个矩形x2,y1加一,这样就把求点转化为求面积,然后每个矩形拆分成上下两个线段,按y排序之后,从下往上每访问一条线段(第一条除外),答案就加上目前整条线段上次数大于等于k的长度乘上这条线段和上一条线段的高度差,然后再用这条线段,根据它是矩形下面还是上面的线段去更新整条线段,维护线段大于等于k的长度这步利用线段树
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson(x) ((x<<1)+1) #define rson(x) ((x<<1)+2) const int N = 30005; int hash[N * 2], hn; int t, n, k; struct Line { int l, r, y, flag; Line() {} Line(int l, int r, int y, int flag) { this->l = l; this->r = r; this->y = y; this->flag = flag; } } line[N * 2]; bool cmp(Line a, Line b) { return a.y < b.y; } void init() { scanf("%d%d", &n, &k); int x1, y1, x2, y2; for (int i = 0; i < n; i++) { scanf("%d%d%d%d", &x1, &y1, &x2, &y2); x2++; y2++; hash[i] = x1; hash[i + n] = x2; line[i] = Line(x1, x2, y1, 1); line[i + n] = Line(x1, x2, y2, -1); } hn = 1; sort(hash, hash + 2 * n); for (int i = 1; i < 2 * n; i++) { if (hash[i] != hash[i - 1]) hash[hn++] = hash[i]; } sort(line, line + 2 * n, cmp); } int F(int x) { int l = 0, r = hn - 1; while (l < r) { int mid = (l + r) / 2; if (hash[mid] < x) l = mid + 1; else r = mid; } return l; } struct Node { int l, r, sum[11], kv; Node() {} Node(int l, int r) { this->l = l; this->r = r; memset(sum, 0, sizeof(sum)); kv = 0; } } node[N * 8]; void build(int l, int r, int x = 0) { node[x] = Node(l, r); node[x].sum[0] = hash[r + 1] - hash[l]; if (l == r) return; int mid = (l + r) / 2; build(l, mid, lson(x)); build(mid + 1, r, rson(x)); } void pushup(int x) { memset(node[x].sum, 0, sizeof(node[x].sum)); if (node[x].l == node[x].r) node[x].sum[min(k, max(0, node[x].kv))] = hash[node[x].r + 1] - hash[node[x].l]; else { for (int i = 0; i <= k; i++) node[x].sum[min(k, max(0, i + node[x].kv))] += node[lson(x)].sum[i] + node[rson(x)].sum[i]; } } void add(int l, int r, int v, int x = 0) { if (node[x].l >= l && node[x].r <= r) { node[x].kv += v; pushup(x); return; } int mid = (node[x].l + node[x].r) / 2; if (l <= mid) add(l, r, v, lson(x)); if (r > mid) add(l, r, v, rson(x)); pushup(x); } long long solve() { build(0, hn - 2); long long ans = 0; for (int i = 0; i < 2 * n; i++) { if (i) ans += (long long)(line[i].y - line[i - 1].y) * node[0].sum[k]; add(F(line[i].l), F(line[i].r) - 1, line[i].flag); } return ans; } int main() { int cas = 0; scanf("%d", &t); while (t--) { init(); printf("Case %d: %lld\n", ++cas, solve()); } return 0; }
UVA 11983 - Weird Advertisement(线段树)
时间: 2024-11-11 06:48:57