您的位置:首页 > 其它

HDU 4052 Adding New Machine (线段树)

2015-10-21 12:02 411 查看
题意:有一个w*h的矩阵,里面放着n个矩形,现在有一个1*m的矩形要放置到这个矩形中,问有多少种放法。

思路:对于一种放法,只要求出可以放置矩形的起点组成的面积就行,那么我们可以把这个问题转化为求矩形面积交。

对于横放和竖放分别求起点组成的面积,对于横放,那么矩形靠前的那条边的前m-1个位置不能当做矩形的起点,这样我们求出不能当矩形起点的面积,然后做差就行,特别要注意当m为1的时候,因为这时候横放竖放都一样,所以答案要除以2。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int MAXN = 250000;
struct Node {
int l, r, c;
int lf, rf, cnt;
} segTree[MAXN*4];
struct Line {
int c;
int x, y1, y2;
bool operator < (const Line& E) const {
return x < E.x;
}
} line[MAXN], line2[MAXN];
int y[MAXN], y2[MAXN];
void build(int o, int L, int R) {
Node& t = segTree[o];
t.l = L;
t.r = R;
t.c = 0;
t.lf = y[L];
t.rf = y[R];
t.cnt = 0;
if(L+1 >= R) return;
int M = (L+R) >> 1;
build(o<<1, L, M);
build((o<<1)|1, M, R);
}
void cal(int o) {
Node& t = segTree[o];
if(t.c > 0) {
t.cnt = t.rf - t.lf;
return;
}
if(segTree[o].l+1 >= segTree[o].r) t.cnt = 0;
else t.cnt = segTree[o<<1].cnt + segTree[(o<<1)|1].cnt;
}
void update(int o, Line e) {
//if(e.y1 >= e.y2) return;
Node& t = segTree[o];
if(e.y1==t.lf && e.y2==t.rf) {
t.c += e.c;
cal(o);
return;
}
if(e.y2 <= segTree[o<<1].rf) update(o<<1, e);
else if(e.y1 >= segTree[(o<<1)|1].lf) update((o<<1)|1, e);
else {
Line tmp = e;
tmp.y2 = segTree[o<<1].rf;
update(o<<1, tmp);
e.y1 = segTree[(o<<1)|1].lf;
update((o<<1)|1, e);
}
cal(o);
}
int n, tot, w, h, m;
int main() {
freopen("input.txt", "r", stdin);
while(scanf("%d%d%d%d", &w, &h, &n, &m) == 4) {
LL ans = 0;
tot = 0;
for(int i = 1; i <= n; i++) {
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
x1--; y1--;
tot++;
Line& t = line[tot];
t.c = 1;
t.x = x1;
t.y1 = y1;
t.y2 = y2;
y[tot] = y1;
tot++;
Line& t2 = line[tot];
t2.c = -1;
t2.x = x2;
t2.y1 = y1;
t2.y2 = y2;
y[tot] = y2;
}
for(int i = 1; i <= tot; i++) line2[i] = line[i];
for(int i = 1; i <= tot; i++) y2[i] = y[i];
for(int i = 1; i <= tot; i++) {
Line& t = line[tot+i];
t = line[i];
t.y2 = line[i].y1;
t.y1 = max(0, line[i].y1-m+1);
y[tot+i] = t.y1;
i++;
Line& t2 = line[tot+i];
t2 = line[i];
t2.y2 = line[i].y1;
t2.y1 = max(0, line[i].y1-m+1);
y[tot+i] = t.y2;
}
line[2*tot+1].x = 0;
line[2*tot+1].y2 = h;
line[2*tot+1].y1 = max(h-m+1, 0);
line[2*tot+1].c = 1;
y[2*tot+1] = h;
line[2*tot+2].x = w;
line[2*tot+2].y2 = h;
line[2*tot+2].y1 = max(h-m+1, 0);
line[2*tot+2].c = -1;
y[2*tot+2] = max(h-m+1, 0);
sort(line+1, line+2*tot+3);
sort(y+1, y+2*tot+3);
build(1, 1, 2*tot+2);
LL tmp = 0;
//for(int i = 1; i <= 2*tot+2; i++) cout << y[i] << endl;
//cout << line[1].x << " " << line[1].y1 << " " << line[1].y2 << " " << line[1].c << endl;
update(1, line[1]);
//puts("Fuck");
for(int i = 2; i <= (tot<<1)+2; i++) {
tmp += (LL)(line[i].x-line[i-1].x)*segTree[1].cnt;
update(1, line[i]);
//cout << tmp << endl;
}
//cout << tmp << endl;
ans += (LL)w*h - tmp;
//cout << ans << endl;
for(int i = 1; i <= tot; i++) line[i] = line2[i];
for(int i = 1; i <= tot; i++) y[i] = y2[i];
for(int i = 1; i <= tot; i++) {
Line& t = line[tot+i];
t = line[i];
t.x = max(0, t.x-m+1);
y[tot+i] = t.y1;
i++;
Line& t2 = line[tot+i];
t2 = line[i];
t2.x = line[i-1].x;
y[tot+i] = t.y2;
}
line[2*tot+1].x = max(0, w-m+1);
line[2*tot+1].y2 = h;
line[2*tot+1].y1 = 0;
line[2*tot+1].c = 1;
y[2*tot+1] = 0;
line[2*tot+2].x = w;
line[2*tot+2].y2 = h;
line[2*tot+2].y1 = 0;
line[2*tot+2].c = -1;
y[2*tot+2] = h;
sort(line+1, line+2*tot+3);
sort(y+1, y+2*tot+3);
build(1, 1, 2*tot+2);
tmp = 0;
update(1, line[1]);
for(int i = 2; i <= (tot<<1)+2; i++) {
tmp += (LL)(line[i].x-line[i-1].x)*segTree[1].cnt;
update(1, line[i]);
}
//cout << tmp << endl;
ans += (LL)w*h - tmp;
//cout << ans << endl;
if(m==1) ans >>= 1;
cout << ans << endl;
}
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU 线段树