[luogu] P2519 [HAOI2011]problem a (贪心)

Posted hhh1109

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu] P2519 [HAOI2011]problem a (贪心)相关的知识,希望对你有一定的参考价值。

P2519 [HAOI2011]problem a

题目描述

一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低。”问最少有几个人没有说真话(可能有相同的分数)

输入输出格式

输入格式:

第一行一个整数n,接下来n行每行两个整数,第i+1行的两个整数分别代表ai、bi

输出格式:

一个整数,表示最少有几个人说谎

输入输出样例

输入样例#1: 复制

3
2 0
0 2
2 2

输出样例#1: 复制

1

说明

100%的数据满足: 1≤n≤100000 0≤ai、bi≤n

题解

本题因为过度巧妙引起极度不适。
看题十分钟。。。暴力都不会。
日常开题解。

我只想到了对于一个人,
([a_i+1,n-b_i])内累计人数超过的这个区间的就不算了。
还有本身矛盾的就是(a_i+b_i>=n)
然后怎么做啊。。。
一看题解,做完了。。。
我们把人转为([a_i+1,n-b_i])的区间以后,这个区间有一个价值,就是当前描述位于这个区间合法(有没有多于这个区间)的人数。
然后dp求一下第i个人时的最大值就可以了。

(f[i]=max(f[i-1],f[next]+val);)

Code

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<map>
#include<vector>
using namespace std;
const int N=1e6+5;
int n,f[N];
vector<int>q[N];
map<pair<int,int>,int>mp;

int read(){
    int x=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*w;
}

int main(){
    n=read();
    for(int i=1;i<=n;i++){
        int l=read(),r=read();
        l++;r=n-r;
        if(l>r)continue;
        if(++mp[make_pair(l,r)]==1)
            q[r].push_back(l);
    }
    for(int i=1;i<=n;i++){
        f[i]=f[i-1];
        for(int j=0;j<q[i].size();j++)
        f[i]=max(f[i],f[q[i][j]-1]+min(i-q[i][j]+1,mp[make_pair(q[i][j],i)]));
    }
    cout<<n-f[n]<<endl;
    return 0;   
} 

以上是关于[luogu] P2519 [HAOI2011]problem a (贪心)的主要内容,如果未能解决你的问题,请参考以下文章

P2519 [HAOI2011]problem a

p2519 [HAOI2011]problem a

P2519 [HAOI2011]problem a

「Luogu2522」[HAOI2011]Problem b

Luogu-2521 [HAOI2011]防线修建

luogu2522 [HAOI2011]Problem b