• 51nod 1562 玻璃切割 (STL map+一点点的思考)


    题目来源: 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维的即可。
     
     
    写起来很绕,需要很强的编码能力,不过这与问题的解决办法已经无关了。
     
     
    代码:
    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <vector>
    #include <set>
    #include <math.h>
    #include <queue> 
    #include <assert.h>
    #include <stdio.h>
    #include <stdlib.h>
    using namespace std;
    typedef long long ll;
    #define INF 2147483647
    
    //输入 
    int w, h, n;
    
    //mh:高度方向上每个间隔出现的次数。mh[i] = j表示间隔为i的线段有j个。 
    //mv:宽度方向上每个间隔出现的次数。mv[i] = j表示间隔为i的线段有j个。
    //h1: h1[i] = j表示高度方向上切割点为i的线段的长度为j。
    //v1: v1[i] = j表示宽度方向上切割点为i的线段的长度为j。
    map <int, int> mh, mv, h1, v1;
    map <int, int>::iterator it, it1;
    
    int main() {
        scanf("%d%d%d", &w, &h, &n);
        //初始化,长度为h的线段+1,长度为w的线段+1,以0为起点的线段长为h,以0为起点的线段长为w。 
        mh[h] = 1;
        mv[w] = 1;
        h1[0] = h;
        v1[0] = w;
    
        char k1;
        int k2;
        while (n--) {
            getchar();
            scanf("%c%d", &k1, &k2);
    
            if (k1 == 'H') {
                //找到切割点前一个点的位置和长度。 
                it = h1.lower_bound(k2); it--;
                int con = it->first;
                int len = it->second;
    
                //长度为len的线段-1,如果为0了就从map中删掉 
                mh[len]--;
                if (mh[len] == 0) mh.erase(len);
    
                //h1: h1[i] = j表示高度方向上切割点为i的线段的长度为j。
                h1[con] = k2 - con;
                h1[k2] = len - h1[con];
    
                //mh:高度方向上每个间隔出现的次数。mh[i] = j表示间隔为i的线段有j个。 
                mh[h1[k2]]++;
                mh[h1[con]]++;
    
            }
            else if (k1 == 'V') {
                it = v1.lower_bound(k2); it--;
                int con = it->first;
                int len = it->second;
    
                mv[len]--;
                if (mv[len] == 0) mv.erase(len);
                v1[con] = k2 - con;
                v1[k2] = len - v1[con];
                mv[v1[k2]]++;
                mv[v1[con]]++;
            }
    
            //map最后一个值的key最大 
            it = mh.end(); it--;
            it1 = mv.end(); it1--;
            ll p = it->first;
            ll q = it1->first;
            printf("%lld
    ", p*q);
        }
        getchar(); getchar();
        return 0;
    }
    /*
    10 10 5
    H 1
    H 8
    H 6
    H 2
    H 4
    */
  • 相关阅读:
    卡尔曼滤波的原理与思想
    什么是端口
    什么是ICD文件
    USB口,串口,以太网口简介
    Linux基本操作笔记
    网络营销学习路线图
    读书推荐:2017 第一期
    又见Bug
    如何请教别人问题?
    圆桌问答 (2017 第一季)
  • 原文地址:https://www.cnblogs.com/zhangjiuding/p/7855636.html
Copyright © 2020-2023  润新知