HDU 3642 Get The Treasury(线段树+扫描线求面积【再升级版(三维)】)

题目链接:HDU 3642 Get The Treasury

嘿嘿,早在做二维的时候我就猜到会有三维的~~~

线段树+扫描线求面积 :1.基础版 (HDU 1542) 2.升级版 (HDU 1255)

如今遇到再次升级的版本心里小小的激动了一下

从HDU 1542 单纯求面积,到HDU 1255 求覆盖次数2次及以上的面积,到HDU 3642 求覆盖次数3次及以上的体积

体积的话,因为z的范围不大,所以将z轴的每个点单独枚举,再做二维的求面积,然后乘上高度差(z[i+1]-z[i])

虽然z范围小,不过为了节约时间依旧进行了离散化,因为对每一个z坐标都要进行二维求面积

故而需要将输入保存下来每次使用,然后做二维求面积的操作就和HDU 1255 一样,不过再多加了一个覆盖次数而已

s 表示当前节点控制的x轴区被覆盖的次数
len1 表示被覆盖1次的长度
len2 表示被覆盖2次的长度
len3 表示被覆盖3次及以上的长度 

后来写

q[i].len3 = q[ls].len3 + q[rs].len3;
q[i].len2 = q[ls].len2 + q[rs].len2;
q[i].len1 = q[ls].len1 + q[rs].len1;

这段代码的时候,觉得其实len1,len2,len3可以用数组len[4]来保存,类似的操作就可以用循环写

代码可以和HDU 1255 升级版对比着看

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
/*
	s 表示当前节点控制的x轴区被覆盖的次数
	len1 表示被覆盖1次的长度
	len2 表示被覆盖2次的长度
	len3 表示被覆盖3次及以上的长度 
*/
const int N = 2222;
struct Edge
{
	int l,r;
	int h;
	int f;
	void init(int lx,int rx,int hx,int fx)
	{
		l = lx,r = rx,h = hx,f = fx;
	}
}e[N<<1];
bool cmp(Edge a,Edge b)
{
	return a.h < b.h;
}
struct Node
{
	int l,r;
	int s; //覆盖情况 
	int len1;
	int len2;
	int len3;
}q[N*8];
int x[N<<1],z[N<<1];
#define ls i<<1
#define rs i<<1|1
#define m(i) ((q[i].l + q[i].r)>>1)
void pushup(int i)
{
	int r = q[i].r,l = q[i].l;
	if (q[i].s >= 3)
	{
		q[i].len3 = x[r+1] - x[l];
		q[i].len1 = q[i].len2 = 0;
	}
	else if (q[i].s >= 2) //其实就是等于2
	{
		q[i].len3 = q[ls].len3 + q[rs].len3 + q[ls].len2 + q[rs].len2 + q[ls].len1 + q[rs].len1;
		q[i].len2 = x[r+1] - x[l] - q[i].len3;
		q[i].len1 = 0;
	} 
	else if (q[i].s >= 1) 
	{
		q[i].len3 = q[ls].len3 + q[rs].len3 + q[ls].len2 + q[rs].len2;
		q[i].len2 = q[ls].len1 + q[rs].len1;
		q[i].len1 = x[r+1] - x[l] - q[i].len3 - q[i].len2; 
	} 
	else 
	{
		q[i].len3 = q[ls].len3 + q[rs].len3;
		q[i].len2 = q[ls].len2 + q[rs].len2;
		q[i].len1 = q[ls].len1 + q[rs].len1;
	}
}
void build(int i,int l,int r)
{
	q[i].l = l,q[i].r = r;
	if (l == r) return;
	int mid = m(i);
	build(ls,l,mid);
	build(rs,mid+1,r);
}
void update(int i,int l,int r,int f)
{
	if (l <= q[i].l&&q[i].r <= r)
	{
		q[i].s += f;
		pushup(i);
		return; 
	}
	int mid = m(i);
	if (r <= mid) update(ls,l,r,f);
	else if (l > mid) update(rs,l,r,f);
	else 
	{
		update(ls,l,mid,f);
		update(rs,mid+1,r,f);
	}
	pushup(i);
}
struct Point //需要把输入保存下来 
{
	int x,y,z;
	void init(int xx,int yy,int zz)
	{
		x = xx,y = yy,z = zz;
	}
}a[N<<1];
int main()
{
	int T;cin>>T;int kas = 0;
	while (T--)
	{
		int n;scanf("%d",&n);
		int totx = 0,totz = 0;
		int tot = 0;
		int x1,y1,z1,x2,y2,z2;
		for (int i = 1;i <= n;++i)
		{
			scanf("%d %d %d %d %d %d",&x1,&y1,&z1,&x2,&y2,&z2);
			x[totx++] = x1;x[totx++] = x2;
			z[totz++] = z1;z[totz++] = z2;
			a[tot].init(x1,y1,z1);tot++;
			a[tot].init(x2,y2,z2);tot++;
		}
		printf("Case %d: ",++kas);
		if (n < 3) 
		{
			puts("0");
			continue;
		}
		sort(x,x+totx);
		sort(z,z+totz);
		//利用unique去重函数 
		totx = unique(x,x+totx) - x;
		totz = unique(z,z+totz) - z;
		ll ansxyz = 0;
		for (int i = 0;i < totz-1;++i)//对于每一层z都做一次二维 
		{
			int k = 0;
			for (int j = 0;j < tot;j += 2)
			{
				if (a[j].z <= z[i]&&a[j+1].z > z[i])
				{
					e[k++].init(a[j].x,a[j+1].x,a[j].y,1);//上边
					e[k++].init(a[j].x,a[j+1].x,a[j+1].y,-1);//下边 
				}
			}
			sort(e,e+k,cmp);
			mem(q,0);
			build(1,0,totx-1);
			ll ansxy = 0;
			for (int j = 0;j < k-1;++j)
			{
				int l = lower_bound(x,x+totx,e[j].l) - x;
				int r = lower_bound(x,x+totx,e[j].r) - x - 1;
				update(1,l,r,e[j].f);
				ansxy += (ll)q[1].len3*(ll)(e[j+1].h - e[j].h);
			} 
			ansxyz += (ll)ansxy*(ll)(z[i+1]-z[i]);
		}
		printf("%I64d\n",ansxyz);
	}
	return 0;
}
关于unique 去重函数 : 点击打开链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值