Teodor is not a liar! [CodeForces - 930C]

题意

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

分析

其实翻译起来挺麻烦理解起来有点怕理解错了[?]
其实可以容易的发现,如果所有的点连起来是一个单峰(非降序列+非增序列拼在一起),那么就猜不到答案。但是如果连起来不是单峰而是多峰的话,那么马上就能知道答案了。
所以说,其实就是找到一个最长的单峰。
然后这个通过dp就可以解决了,考虑一个点最大,然后往两遍递减,然后求最长长度就好了。通过树装数组求lis一样的东西,总之很好解决。

code

#include<bits/stdc++.h>
using namespace std;
void read(int &x){
    x=0; char c=getchar();
    for (;c<48;c=getchar());
    for (;c>47;c=getchar())x=(x<<1)+(x<<3)+(c^48);
}
#define M 1000005
int f[M],m,g[M],cnt[M];
void Max(int &x,int y){
    if (x<y)x=y;
}
struct Tree{
    #define lowbit(p) (p&(-p))
    int a[M];
    void add(int p,int x){
        for (;p<M;p+=lowbit(p))Max(a[p],x);
    }
    int qu(int p){
        int res=0;
        for (;p;p-=lowbit(p))Max(res,a[p]);
        return res;
    }
    void clear(){
        memset(a,0,sizeof(a));
    }
}T;

int main(){
//  freopen("1.in","r",stdin);
    int n,res,l,r;
    read(n); read(m);
    for (int i=1;i<=n;i++){
        read(l); read(r);
        cnt[l]++; cnt[r+1]--;
    }
    cnt[1]++;
    for (int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
    for (int i=1;i<=m;i++){
        f[i]=T.qu(cnt[i])+1;
        T.add(cnt[i],f[i]);
    }
    T.clear();
    for (int i=m;i;i--){
        g[i]=T.qu(cnt[i])+1;
        T.add(cnt[i],g[i]);
    }
    for (int i=1;i<=m;i++)Max(res,f[i]+g[i]-1);
    printf("%d\n",res);
    return 0;
}

总结

简单来说就是看题目的时候不要怕吧…其实没有想象的那么困难。

常数

其实挺优秀的[?]
其实是所有人好像都跑这么快…

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值