HDU 4052 Adding New Machine (线段树)

来源:互联网 发布:专业现场音控软件 编辑:程序博客网 时间:2024/05/20 06:49

题意:有一个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;}

0 0
原创粉丝点击