• 牛客2022暑期集训第一场C题 Grab the Seat! 题解


    题目大意

    二维平面,屏幕是 ( 0 , 1 ) – ( 0 , m ) (0, 1)–(0, m) (0,1)(0,m) 的线段,有 n n n m m m列座位在屏幕前面,是坐标范围 $1 ≤ x ≤ n, 1 ≤ y ≤ m 的整点。有 的整点。有 的整点。有k$个座位已经有人,求出到屏幕的视线不被任何人挡住的座位数量。
    题目链接
    一个人挡住的区域是它与屏幕两端连线所形成的夹角区域。
    在这里插入图片描述
    可见视线遮挡是被两条线段确定的,但是实际上,单条连线也能够确定视线遮挡的范围。,对于一条线,水平向右的直线和它自身形成的夹角,是一定被视线遮挡的,而两条线确定的,刚好就是这两个相邻区域的并集
    在这里插入图片描述
    对于当前行,能够覆盖该行的,通过左下角的线,一定是在该行以下,而此时显然斜率越大的线,覆盖的越多。在这里插入图片描述
    所以我们逐行处理的时候,保存斜率最大的直线。

    对于左下角的直线 y = i − 1 x n o w ∗ x + 1 , x = x n o w − 1 y − 1 y = \frac{i - 1}{x_{now}} * x + 1, x = \frac{x_{now}-1}{y-1} y=xnowi1x+1,x=y1xnow1

    x n o w x_{now} xnow表示斜率最大的线来在第 n o w now now行,且 x x x坐标为 x n o w x_{now} xnow

    代码中在分子又额外减一是为了防止结果刚好在整数点上,导致计算错误,因为这个点实际上也是被遮挡的。

    右上角的线也同理

    我们计算每一行没被覆盖的点。然后计算出左上,左下的线分别的结果。然后取min即可。

    代码

    #include 
    #include 
    using namespace std;
    
    const int maxN = 2e5 + 7;
    
    int n, m, k, q, x[maxN], y[maxN], minY[maxN], con[maxN][2];
    
    int main()
    {
        scanf("%d%d%d%d", &n, &m, &k, &q);
        for(int i = 1; i <= k; ++i) 
            scanf("%d%d", &x[i], &y[i]);
        while(q--) {
            int num; scanf("%d", &num);
            scanf("%d%d", &x[num], &y[num]);
            for(int i = 1; i <= m; ++i)
                minY[i] = n + 1;
            for(int i = 1; i <= k; ++i)
                minY[y[i]] = min(minY[y[i]], x[i]);
            int now = 1; con[1][0] = minY[1] - 1;
            for(int i = 2; i <= m; ++i) {
                if((long long) (now - 1) * minY[i] < (long long) (i - 1) * minY[now]) 
                    now = i;
                con[i][0] =  ((long long) (i - 1) * minY[now] - 1) / (now - 1);
            }
            now = m; con[m][1] = minY[m] - 1;   
            for(int i = m - 1; i >= 1; --i) {
                if((long long) (m - now) * minY[i] < (long long) (m - i) * minY[now])
                    now = i;
                con[i][1] = ((long long) (m - i) * minY[now] - 1) / (m - now);
            }
            long long ans = 0;
            for(int i = 1; i <= m; ++i)
                ans += min(con[i][0], con[i][1]);
            printf("%lld\n", ans);
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
  • 相关阅读:
    Sublime和iTerm中使用FiraCode编程连字等宽字体的配置
    openMMLab的mmcv和mmdet、mmdet3d、mmseg版本对应关系
    Kotlin拿Android本地视频缩略图
    HCIA-单臂路由-VLAN-VLAN间通信-OSPF 小型实验
    Spring Boot自动配置原理懂后轻松写一个自己的starter
    Hexo添加jVectorMap足迹地图
    dBm dBi dBd dB dBc解释
    【FPGA】FPGA实现SPI协议读写FLASH(一)----- M25P16操作概述
    Sass常用语法
    ElasticSearch深度分页问题如何解决
  • 原文地址:https://blog.csdn.net/SGDBS233/article/details/125907546