• qduoj 218 签到题


    Description

    a坤和大明在一块由n个方块组成的棋盘(1 × n)上做游戏.一开始a坤在棋盘上放了k个矩形并且没有告诉大明具体位置.每个矩形都占a个连续方块(1 × a),任意两个矩形不可重叠且任意两个矩形至少间隔为1.保证没有矩形超出棋盘范围.之后大明开始进行射击,每当大明射向一个方块时,a坤都会告诉他打没打中.那么问题来了,a坤这个人素质有些问题,就很喜欢骗人,所以他总是告诉大明没打中.你要帮大明抓a坤的现行--a坤第一次可以被确认的撒谎发生在大明第几次射击.

    Input

    多组输入输出,第一行三个整数n,k,a(1 ≤ n, k, a ≤ 2·1e5),分别代表棋盘大小,矩形数量以及每个矩形的大小.保证能够把k个矩形(1 × a)全部按要求放入棋盘内(1 × n).第二行一个整数m,代表小明的射击次数.第三行m个整数p1,p2,...,pm(1 ≤ pi ≤ n),分别代表第i次的射击位置为pi.

    Output

    输出一个整数.如果能抓到a坤现行,就输出大明是在第几次可以确认a坤作弊的,否则输出-1.

    Sample Input 1

    11 3 3
    5
    4 8 6 1 11

    Sample Output 1

    3

    Sample Input 2

    5 1 3
    2
    1 5

    Sample Output 2

    -1

    Sample Input 3

    5 1 3
    1
    3

    Sample Output 3

    1

    二分判断,对于给出的一些没射中的点,在他们之间可以放下多少个矩形,如果数量小于k就表示说谎啦,但是不能排着去查会超时,所以需要二分 ,找到小于k的最靠前位置。可以一开始先判断如果m个数都知道是否可以判断其说谎,如果可以展开二分,如果不可以直接-1.
    set代码:
    #include <iostream>
    #include <cstdio>
    #include <set>
    using namespace std;
    int n,k,a,m,d,s[200005];
    int get(int t) {
        int last = 0,ans = 0;
        set<int> p;
        p.insert(n + 1);
        for(int i = 0;i <= t;i ++) {
            p.insert(s[i]);
        }
        for(set<int>::iterator it = p.begin();it != p.end();it ++) {
            ans += (*it - last) / (a + 1);
            last = *it;
        }
        return ans;
    }
    int main() {
        while(~scanf("%d%d%d",&n,&k,&a)) {
            scanf("%d",&m);
            for(int i = 0;i < m;i ++) {
                scanf("%d",&s[i]);
            }
            int l = 0,r = m - 1,mid;
            if(get(m - 1) >= k)l = -2;
            else
            while(l < r) {
                mid = (l + r) / 2;
                if(get(mid) >= k)l = mid + 1;
                else r = mid;
            }
            printf("%d
    ",l + 1);
        }
    }

     排序代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int n,k,a,m,d,s[200005],s1[200005];
    int get(int t) {///查看前t次给出的点  中间空隙可以放下几个矩形。
        int last = 0,ans = 0;
        for(int i = 0;i <= t;i ++) {
            s1[i] = s[i];
        }
        s1[t + 1] = n + 1;///作为最后的边界,这样可以查看所有的边界
        sort(s1,s1 + t + 1);///从小到大排序
        for(int i = 0;i <= t + 1;i ++) {
            ans += (s1[i] - last) / (a + 1);///除以a + 1是因为两个矩形之间间隔至少为1  而且s1[i] - last的值实际比间隔长度多1
            last = s1[i];///last是上个点 初始为0点
        }
        return ans;
    }
    int main() {
        while(~scanf("%d%d%d",&n,&k,&a)) {
            scanf("%d",&m);
            for(int i = 0;i < m;i ++) {
                scanf("%d",&s[i]);
            }
            int l = 0,r = m - 1,mid;
            if(get(m - 1) >= k)l = -2;///m个点之间可以放下k个矩形 就无法判断说谎
            else
            while(l < r) {///二分查找刚好放不下k个的时候
                mid = (l + r) / 2;
                if(get(mid) >= k)l = mid + 1;
                else r = mid;
            }
            printf("%d
    ",l + 1);
        }
    }
  • 相关阅读:
    MySQL8.0新增配置参数
    CF1153F Serval and Bonus Problem
    win10 uwp xaml 绑定接口
    win10 uwp xaml 绑定接口
    Windows Community Toolkit 3.0 新功能 在WinForms 和 WPF 使用 UWP 控件
    Windows Community Toolkit 3.0 新功能 在WinForms 和 WPF 使用 UWP 控件
    win10 uwp 渲染原理 DirectComposition 渲染
    dotnet 从入门到放弃的 500 篇文章合集
    C# ValueTuple 原理
    WPF 使用 Direct2D1 画图入门
  • 原文地址:https://www.cnblogs.com/8023spz/p/9164447.html
Copyright © 2020-2023  润新知