51nod 1562 玻璃切割 (set+离线处理)

传送门51nod 1562



思路

最核心的思路是离线处理,也就是不用每次切割都立即输出结果,而是先把所有结果处理完再统一输出。用讨论区的话说就是把武功倒着打。


我们注意到,当前面积最大的玻璃一定是横向最大长度乘以纵向最大长度,所以我们只需要维护横向和纵向的最大长度就可以了。如果是每次切割都要计算面积的话,我们不禁要求出新产生的两块玻璃的长度,还要删除切割前的长度。这样就导致时间消耗比较大。


如果离线处理的话,相当于我们已经把玻璃全部切割完,现在需要从后往前依次去掉一根切割线,然后计算面积。这样玻璃的长度一定会增大,所以只需要维护玻璃横向和纵向的最大值即可。


具体做法就是把横向和纵向的切割线分别放入两个集合,求出最大的横向距离和纵向距离。从后往前依次去掉一个切割线(在集合中删除),然后查找该切割线左右两边的切割线并更新该方向上长度的最大值。



代码

#include<stdio.h>
#include<iostream>
#include<set>
using namespace std;
typedef long long LL;

LL ans[200010]; //存放结果 

int main()
{		
	int i,w,h,n,maxr,maxc,x[200010];
	char c[200010]; //在哪个方向切割 
	set<int> row,col; //行和列上的切割线 
	set<int>:: iterator it;
	while(~scanf("%d%d%d",&w,&h,&n))
	{
		maxr=maxc=0;
		row.clear(); //清空集合 
		col.clear();
		row.insert(0); //插入开始时的两端 
		row.insert(h);
		col.insert(0);
		col.insert(w);
		for(i=0;i<n;i++)
		{ //读入操作并将切割线插入到相应集合 
			scanf("%*c%c%d",&c[i],&x[i]);
			if(c[i]=='H') row.insert(x[i]);
			else col.insert(x[i]);
		}
		int l,r;				
		for(it=row.begin();it!=row.end();)
		{ //求纵向上长度的最大值 
			l=*it;
			it++;
			r=*it;
			if(r-l>maxr) maxr=r-l;
		}
		for(it=col.begin();it!=col.end();)
		{ //求横向上长度的最大值 
			l=*it;
			it++;
			r=*it;					
			if(r-l>maxc) maxc=r-l;
		}
		for(i=n-1;i>=0;i--)
		{ //从后往前处理 
			ans[i]=(LL)maxr*maxc; //先计算结果 
			if(c[i]=='H')
			{ //如果是横向切割 
				it=row.lower_bound(x[i]); //二分查找当前切割线的位置 
				it--;
				l=*it;
				it++;
				it++;
				r=*it;
				if(r-l>maxr) maxr=r-l; //维护最大值 
				row.erase(x[i]); //删除该切割线 
			}
			else
			{ //如果是纵向切割
				it=col.lower_bound(x[i]); //二分查找当前切割线的位置 
				it--;
				l=*it;
				it++;
				it++;
				r=*it;
				if(r-l>maxc) maxc=r-l; //维护最大值 
				col.erase(x[i]); //删除该切割线 
			}
		}
		for(i=0;i<n;i++) printf("%lld\n",ans[i]);			
	}
	return 0;
}


  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值