UVA 1492 - Adding New Machine(线段树)

UVA 1492 - Adding New Machine

题目链接

题意:给定一些旧机器管辖范围,现在要放一台进新机器,新机器需要空间1*m,问有多少种放法

思路:转化为求面积并的问题,先考虑横放,对于旧机器左边m个位置肯定不能放,还有边界w-m之后的位置肯定不能放,这样就可以把旧机器向左扩大m个位置,并且边界多上一块m*h大小的面积,这样求出这些面积并再用总面积减去即可,求面积的方法利用线段树扫描线,然后对于竖放再做一遍即可,注意特判m=1的情况

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define lson(x) ((x<<1)+1)
#define rson(x) ((x<<1)+2)

typedef long long ll;
const int N = 100005;

struct Line {
    int l, r, h, flag;
    Line() {}
    Line(int l, int r, int h, int flag) {
	this->l = l; this->r = r;
	this->h = h; this->flag = flag;
    }
} li[N];

struct Point {
    int x1, y1, x2, y2;
} p[N];

bool cmp(Line a, Line b) {
    return a.h < b.h;
}

ll w, h;
int n, m, tot, hash[N], hn;

int find(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;
}

void gethash() {
    hn = 0;
    for (int i = 0; i < tot; i++) {
	if (li[i].flag == 1) continue;
	hash[hn++] = li[i].l;
	hash[hn++] = li[i].r;
    }
    sort(hash, hash + hn);
    int tmp = hn;
    hn = 1;
    for (int i = 1; i < tmp; i++)
	if (hash[i] != hash[i - 1])
	    hash[hn++] = hash[i];
}

struct Node {
    int l, r, addv, len;
    Node() {}
    Node(int l, int r, int addv = 0, int len = 0) {
	this->l = l;
	this->r = r;
	this->addv = addv;
	this->len = len;
    }
} node[N * 4];

void build(int l, int r, int x = 0) {
    node[x] = Node(l, r);
    if (l == r)
	return;
    int mid = (l + r) / 2;
    build(l, mid, lson(x));
    build(mid + 1, r, rson(x));
}

void pushup(int x) {
    if (node[x].addv) node[x].len = hash[node[x].r + 1] - hash[node[x].l];
    else if (node[x].l == node[x].r) node[x].len = 0;
    else node[x].len = node[lson(x)].len + node[rson(x)].len;
}

void insert(int l, int r, int v, int x = 0) {
    if (node[x].l >= l && node[x].r <= r) {
	node[x].addv += v;
	pushup(x);
	return;
    }
    int mid = (node[x].l + node[x].r) / 2;
    if (l <= mid) insert(l, r, v, lson(x));
    if (r > mid) insert(l, r, v, rson(x));
    pushup(x);
}

ll solve() {
    if (n == 0) return h * (w - m + 1);
    ll ans = 0;
    sort(li, li + tot, cmp);
    gethash();
    build(0, hn - 2);
    for (int i = 0; i < tot; i++) {
	if (i) ans += (ll)node[0].len * (li[i].h - li[i - 1].h);
	insert(find(li[i].l), find(li[i].r) - 1, li[i].flag);
    }
    return h * w - ans;
}


ll init() {
    ll ans = 0;
    tot = 0;
    for (int i = 0; i < n; i++) {
	scanf("%d%d%d%d", &p[i].x1, &p[i].y1, &p[i].x2, &p[i].y2);
	li[tot++] = Line(max(0, p[i].x1 - m), p[i].x2, p[i].y1 - 1, 1);
	li[tot++] = Line(max(0, p[i].x1 - m), p[i].x2, p[i].y2, -1);
    }
    li[tot++] = Line(max(0, (int)w - m + 1), w, 0, 1);
    li[tot++] = Line(max(0, (int)w - m + 1), w, h, -1);
    ans += solve();
    tot = 0;
    for (int i = 0; i < n; i++) {
	li[tot++] = Line(max(0, p[i].y1 - m), p[i].y2, p[i].x1 - 1, 1);
	li[tot++] = Line(max(0, p[i].y1 - m), p[i].y2, p[i].x2, -1);
    }
    li[tot++] = Line(max(0, (int)h - m + 1), h, 0, 1);
    li[tot++] = Line(max(0, (int)h - m + 1), h, w, -1);
    swap(w, h);
    ans += solve();
    if (m == 1) ans /= 2;
    return ans;
}

int main() {
    while (~scanf("%lld%lld%d%d", &w, &h, &n, &m)) {
	printf("%lld\n", init());
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值