现在有一块玻璃,是长方形的(w 毫米× h 毫米),现在要对他进行切割。
切割的方向有两种,横向和纵向。每一次切割之后就会有若干块玻璃被分成两块更小的玻璃。在切割之后玻璃不会被移动。
现在想知道每次切割之后面积最大的一块玻璃是多少。
样例解释:
对于第四次切割,下面四块玻璃的面积是一样大的。都是2。
Input
单组测试数据。 第一行有三个整数 w,h,n (2≤w,h≤200000, 1≤n≤200000),表示玻璃在横向上长w 毫米,纵向上长h 毫米,接下来有n次的切割。 接下来有n行输入,每一行描述一次切割。 输入的格式是H y 或 V x。 H y表示横向切割,切割线距离下边缘y毫米(1≤y≤h-1)。 V x表示纵向切割,切割线距离左边缘x毫米(1≤x≤w-1)。 输入保证不会有两次切割是一样的。
Output
对于每一次切割,输出所有玻璃中面积最大的是多少。
Input示例
样例输入1 4 3 4 H 2 V 2 V 3 V 1
Output示例
样例输出1 8 4 4 2
思路:对于求每次分割的最大区域面积,即求每次长和宽的最大长度。而要求最大值,则可以将所有切割线段按先后顺序保存下来,用mw,mh分别保存长宽的最大值,再从后面开始一个个将切割线段 ai 去掉,在去掉 ai 时,则将 ai所在的线段合并,再和最大值比较。因此需要预先将 每个切割线段的左右线段记录即可。
Code :
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
struct node{
int l;
int r;
};
const int MAX_N=200005;
int n,w,h;
int a[MAX_N][2];
vector<int> wi,hi; //所有切割线段
node dw[MAX_N],dh[MAX_N]; //dw[i] 切割线段 i 的左右切割线段
LL ans[MAX_N];
int main()
{
ios::sync_with_stdio(false);
cin>>w>>h>>n;
char c;
for(int i=0;i<n;++i)
{
cin>>c>>a[i][1];
if(c=='V'){
a[i][0]=1;
wi.push_back(a[i][1]);
}else hi.push_back(a[i][1]);
}
sort(wi.begin(),wi.end());
sort(hi.begin(),hi.end());
int mw=0,mh=0;
int l=0;
int tt=wi.size()-1;
for(int i=0;i<tt;++i)
{
mw=max(mw,wi[i]-l);
dw[wi[i]]=node{l,wi[i+1]};
l=wi[i];
}
if(wi.size()){
mw=max(mw,wi[wi.size()-1]-l);
mw=max(mw,w-wi[wi.size()-1]);
dw[wi[wi.size()-1]]=node{l,w};
}else mw=w;
l=0;
tt=hi.size()-1;
for(int i=0;i<tt;++i)
{
mh=max(mh,hi[i]-l);
dh[hi[i]]=node{l,hi[i+1]};
l=hi[i];
}
if(hi.size()){
mh=max(mh,hi[hi.size()-1]-l);
mh=max(mh,h-hi[hi.size()-1]);
dh[hi[hi.size()-1]]=node{l,h};
}else mh=h;
for(int i=n-1;i>=0;--i)
{
ans[i]=(LL)mw*mh;
if(a[i][0]==1){
node t=dw[a[i][1]];
dw[t.l].r=t.r;
dw[t.r].l=t.l;
mw=max(mw,t.r-t.l);
}else{
node t=dh[a[i][1]];
dh[t.l].r=t.r;
dh[t.r].l=t.l;
mh=max(mh,t.r-t.l);
}
}
for(int i=0;i<n;++i)
cout<<ans[i]<<endl;
return 0;
}