玻璃切割

 玻璃切割

【题目描述】

现在有一块玻璃,是长方形的(w 毫米× h 毫米),现在要对他进行切割。切割的方向有两种,横向和纵向。每一次切割之后就会有若干块玻璃被分成两块更小的玻璃。在切割之后玻璃不会被移动。

现在想知道每次切割之后面积最大的一块玻璃是多少。

【输入格式】

单组测试数据。

第一行有三个整数 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)。

输入保证不会有两次切割是一样的。

【输出格式】

对于每一次切割,输出所有玻璃中面积最大的是多少。

 

【样例输入】

4 3 4

H 2

V 2

V 3

V 1

【样例输出】

8

4

4


分析:

倒过来处理,如果当前位置x是割线,那么H[x].l表示该割线左面那条割线的位置,H[x].r表示该割线右面那条割线的位置,H[i].val表示该割线与左面那条割线之间的长度,这样每次增加割线倒过来之后就相当于删除割线,当然每次删除只要O(1)更新这条割线左右两边割线的值就好,每次答案就是max(H[i].val)*max(V[i].val)i[0,w(h)]

总复杂度:O(n)

#include<iostream> 
#include<cstdio>
#include<set>
#include<cmath>
#include<cstring>
using namespace std;

int mh[200005],mv[200005];
int n,h,v,x;
long long maxh,maxv;
char op;
set<int>H,V;

void cut(set<int>& s,int *a,int val)
{
    s.insert(val);
    set<int>::iterator l,r;
    l=r=s.find(val);
    l--,r++;
    a[*r-*l]--;
    a[*r-val]++;
    a[val-*l]++;
}

int main()
{
    //freopen("cut.in","r",stdin); 
    //freopen("cut.out","w",stdout); 
    scanf("%d%d%d",&v,&h,&n);
    mh[h]=1,mv[v]=1;
    H.insert(h),V.insert(v);
    H.insert(0),V.insert(0);
    maxh=h,maxv=v;
    while(n--)
    {
        cin>>op>>x;
        if(op=='H')
        {
            cut(H,mh,x);
        }
        else
        {
            cut(V,mv,x);
        }
        while(!mh[maxh])maxh--;
        while(!mv[maxv])maxv--;
        printf("%I64d\n",maxh*maxv);
    }
    return 0;
}

 

 

 

 

猜你喜欢

转载自www.cnblogs.com/mark2017/p/9169009.html
今日推荐