51nod1562割玻璃

题目来源: CodeForces
基准时间限制:1.5 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
 收藏
 关注

现在有一块玻璃,是长方形的(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
这道题题意以及思路比较清楚:动态的维护行列上线段的最大值,每段线段可以在一次操作中被分成两段
一种思路:各种数据结构乱搞,反正200000,我开始用了一发set,超了一个点
另一种:区分线段比较难实现,不如合并,先把所有的线段都拆好,把操作到过来做,每次合并两个线段,统计最大值,写起来有点像DLX
发现思路和标程差不多,慢5倍,头文件的锅,貌似stdio.h超级快
先放个set的程序
#include <iostream>
#include<cstdio>
#include<algorithm>
#include <set>
#define ll long long
using namespace std; 
     
set<ll> stw, sth;
multiset<ll> valuew, valueh;
ll read(){ ll ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
int main(){
    ll w=read(), h=read(), n=read();
    multiset<ll>::iterator it;
    valueh.insert(h);
    valuew.insert(w);
    stw.insert(0), stw.insert(w);
    sth.insert(0), sth.insert(h);
    ll fx=h,fy=w;
    while(n--){
        char str[5];
        ll x;
        scanf("%s", str);
        x=read();
        if(str[0]=='H'){
            it=sth.lower_bound(x);
            ll h1=*it;
            it--;
            ll h2=*it;
            it=valueh.find(h1-h2);
            valueh.erase(it);
            valueh.insert(x-h2);
            valueh.insert(h1-x);
            sth.insert(x);
            fx=*(valueh.rbegin());
        }else{
            it=stw.lower_bound(x);
            ll w1=*it;
            it--;
            ll w2=*it;
            it=valuew.find(w1-w2);
            valuew.erase(it);
            valuew.insert(x-w2);
            valuew.insert(w1-x);
            stw.insert(x);
            fy=*(valuew.rbegin());
        }
        
        
        printf("%lld\n", fx*fy);
    }
    return 0;
}

然后是第二种思路:

#include<stdio.h>
#include<algorithm>
#define ll long long
#define maxn 200005
using namespace std;

typedef struct
{
    char ch;
    ll pos;
} RES;
typedef struct
{
    ll l,val,r;
} WORK;
WORK H[maxn],V[maxn]; 
RES que[maxn];
ll fx[maxn],fy[maxn];
ll w,h,n,ansx,ansy,now;
ll ans[maxn];
int main()
{
    
    scanf("%lld %lld %lld",&w,&h,&n);
    fx[0]=fx[h]=fy[0]=fy[w]=1;
    for(int i=1;i<=n;i++)
    {
        scanf(" %c%lld",&que[i].ch,&que[i].pos);
        if(que[i].ch=='H') fx[que[i].pos]=1;else fy[que[i].pos]=1;
    }
    ansx=ansy=0;
    for(int i=now=0;i<=h;i++)
    {
        if(fx[i]==1)
            H[i].l=now,H[i].val=i-now,H[now].r=i,now=i,ansx=max(ansx,H[i].val);
    }
    H[h].r=h;
    for(int i=now=0;i<=w;i++)
    {
        if(fy[i]==1)
            V[i].l=now,V[i].val=i-now,V[now].r=i,now=i,ansy=max(ansy,V[i].val);
    }
    V[w].r=w;
    ans[n]=ansx*ansy;
    for(int i=n;i>=2;i--)
    {
        if(que[i].ch=='H')
        {
            H[H[que[i].pos].r].val=H[que[i].pos].val+H[H[que[i].pos].r].val;
            H[H[que[i].pos].l].r=H[que[i].pos].r;
            H[H[que[i].pos].r].l=H[que[i].pos].l;
            ansx=max(ansx,H[H[que[i].pos].r].val);
        }else
        { 
            V[V[que[i].pos].r].val=V[que[i].pos].val+V[V[que[i].pos].r].val;
            V[V[que[i].pos].l].r=V[que[i].pos].r;
            V[V[que[i].pos].r].l=V[que[i].pos].l;
            ansy=max(ansy,V[V[que[i].pos].r].val);
        }
        ans[i-1]=ansx*ansy; 
    }
    for(int i=1;i<=n;i++)
        printf("%lld\n",ans[i]);
    
 } 

 





posted @ 2017-08-12 16:07  dancer16  阅读(135)  评论(0编辑  收藏  举报
描述