HDU 4052 Adding New Machine (线段树)

题意:有一个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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值