Codeforces931F Teodor is not a liar!

本文介绍了一种通过询问特定点的覆盖次数来判断是否存在整点被所有线段覆盖的方法。通过对猜测过程的设计,实现了确定答案所需的最少询问次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 题目大意:有一条线段,上面的点被若干条线段覆盖着. Sasha想知道是否存在一个整点被所有的线段覆盖,她每次可以任选一个点,Teodor会告诉她这个点被多少个线段覆盖,但是Sasha不知道有多少条线段.求Sasha最多猜多少次还不知道这个问题的答案. 也就是说,如果你最多猜n次能知道答案,那么输出n-1.如果猜不到答案就输出n.

分析:这种题目把图一画,各种情况考虑一下就能做出来了.

   什么情况下Sasha能知道答案呢? 在这幅图中,1,2,3都被猜过了,覆盖2的线段数小于覆盖1,3的,而线段是连续的,说明有线段到2这个点就中断了,自然就没有整点被所有的线段给覆盖了. 同样的,如果覆盖2的线段数大于覆盖1,3的,也是能够猜出来的. 为了使猜的次数最多,把1,3全都猜完就行了.

   所以究竟是求什么呢? 要求猜的数组成的子序列中不能有两个凸起的部分,只能一边是单调函数,另一边也是单调函数.


代码:

#include <bits/stdc++.h>

using namespace std;
#define SZ(X) ((int)X.size())
#define mp make_pair
#define pb push_back
#define RALL(X) X.rbegin(),X.rend()
#define ALL(X) X.begin(),X.end()

using ll = long long ;
using ld = long double ;


const int N = 1E5 + 7;
const int INF = 0x3f3f3f3f;

int a[N];
int dp1[N];
int dp2[N];
int f1[N];
int f2[N];
int n, q;

int main()
{
    scanf("%d %d", &q, &n);
    for(int i = 1;i <= q;i ++) {
        int l, r;
        scanf("%d %d",&l, &r);
        a[l] ++;
        a[r+1] --;
    }
    for(int i = 1;i <= n;i ++) a[i] += a[i-1];
    int len = 1;
    fill(dp1+1, dp1+1+n, INF);
    fill(dp2+1, dp2+1+n, -INF);
    dp1[1] = a[1];
    f1[1] = 1;
    for(int i = 2;i <= n;i ++) {
        if(a[i] >= dp1[len]) {
            dp1[++len] = a[i];
        } else {
            int pos = upper_bound(dp1 + 1, dp1 + 1 + len, a[i]) - dp1;
            dp1[pos] = a[i];
        }
        f1[i] = len;
    }
    len = 1;
    dp2[1] = a[n];
    for(int i = n - 1;i >= 1;i --) {
        if(a[i] >= dp2[len]) {
            dp2[++len] = a[i];
        } else {
            int pos = upper_bound(dp2 + 1, dp2 + 1 + len, a[i]) - dp2;
            dp2[pos] = a[i];
        }
        f2[i] = len;
    }
    int res = 0;
    for(int i = 1;i <= n;i ++) res = max(res, f1[i]+f2[i]-1);
    printf("%d\n", res);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值