51Nod 1562 玻璃切割 (set)

本博客探讨了如何解决51Nod的1562题——玻璃切割问题,这是一个涉及矩形切割的多维问题。通过将问题转化为一维线段切割,并利用集合(set)和多重集合(multiset)来维护切点和线段长度,可以实现log(N)的时间复杂度。然而,51Nod上的解决方案可能会遇到TLE,因此提出了使用集合加辅助数组的优化策略,以减少重复操作。虽然优化后的代码可能在某些情况下仍然超时,但在大多数情况下能AC。

联动:CodeForces - 527C Glass Carving (二分+set) 多维矩形切割问题

是同一道题,51Nod 数据加强。

题意:

        给出一个高为 H ,宽为 V 的矩形。要经过 N 次切割,问每次切割后最大的一块是多少?

思路:

       首先注意乘积爆 INT 。

       为简化思考,本题题意为二维切割,我们不妨先考虑将问题转化为一位线段的切割问题思考。

       我们可以通过维护 切点 及 从每个切点开始的线段长度 得知每次操作后的最大长度。

       即 利用 数组 维护从每个切点开始的线段长度

            利用 set 维护 切点

            利用 multiset 维护 所有线段的长度 以便求最大长度

       在增加切点时利用 set 的二分查找和 multiset 的相关操作可以将效率压在 log(N)。

       二维,多维同理

       但是在 51 nod 仍是TLE 的。

       于是进行了如下优化:

       所有线段的长度 利用 set + 一个数组 维护,免去重复删除同样长度数据带来的多余的操作。

       优化后仍有可能超时,但最多 100ms。

       所以以下代码得看服务器心情 AC 。

代码:

#include <bits/stdc++.h>
using namespace std;
set<int> xset,yset;
set<int> ansx,ansy;
set<int>::iterator it1,it2;
const int MAXN=200000+10;
int xare[MAXN],yare[MAXN],opv[MAXN];
char opc[MAXN];
int main(){
    int n,m,k,v,l,r;
    long long ans;
    char ch;
    while(scanf("%d %d %d",&n,&m,&k)!=-1){
        getchar();
        memset(xare,0,sizeof(xare));
        memset(yare,0,sizeof(yare));
        xset.clear();yset.clear();ansx.clear();ansy.clear();
        xset.insert(0);xset.insert(n);
        yset.insert(0);yset.insert(m);
        ansx.insert(n),ansy.insert(m);
        xare[n]++;yare[m]++;
        for(int i=0;i<k;i++){
            scanf("%c %d",&opc[i],&opv[i]);getchar();
        }
        for(int i=0;i<k;i++){
            ch=opc[i];v=opv[i];
            if(ch=='V'){
                it2=it1=xset.lower_bound(v);
                it1--;
                l=*it1;
                r=*it2;
                if(--xare[r-l]==0) ansx.erase(r-l);
                ansx.insert(v-l);ansx.insert(r-v);xset.insert(v);
                xare[v-l]++;xare[r-v]++;
            }else{
                it2=it1=yset.lower_bound(v);
                it1--;
                l=*it1;
                r=*it2;
                if(--yare[r-l]==0) ansy.erase(r-l);
                ansy.insert(v-l);ansy.insert(r-v);yset.insert(v);
                yare[v-l]++;yare[r-v]++;
            }
            ans=*(--ansy.end());
            ans*=*(--ansx.end());
            printf("%lld\n",ans);
        }
    }
}


题目来源:  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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值