您的位置:首页 > 其它

[HAOI2011][BZOJ2298] problem a

2015-07-13 20:58 309 查看

2298: [HAOI2011]problem a

Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 766 Solved: 346
[Submit][Status][Discuss]

Description

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

Input

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

Output

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

Sample Input

3

2 0

0 2

2 2

Sample Output

1

HINT

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

首先,要求最少说谎人数,即最大说真话人数。

对于每一个人,有a[i]个比他分数高的,b[i]个比他分数低的。则若序列为单调不增序列,和他同分的人的序号一定在a[i]+1->n-b[i]之间。因此可以想象成一段线段,问题转化为在一个长度为n的线段上有几段线段,求几段不想交的线段的长度之和,使这个值最大。

于是就是一个dp的题目了。方程显而易见。

又了解了一个map,在黄学长题解里还看到了动态数组?自己STL好弱……过几天系统学一下。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
map <pair<int,int>,int> s;
int a,b,n,m,dp[100001],head[100001],next[100001],list[100001];
void add(int x,int y)
{
next[++m]=head[x];
head[x]=m;
list[m]=y;
}
int main()
{
scanf("%d",&n);
m=0;
for (int i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
if (a+b>=n) continue;
a++;
b=n-b;
if (!s[make_pair(a,b)]) add(b,a);
s[make_pair(a,b)]=min(s[make_pair(a,b)]+1,b-a+1);
}
for (int i=1;i<=n;i++)
{
dp[i]=dp[i-1];
for (int j=head[i];j;j=next[j])
{
int u=list[j]-1;
dp[i]=max(dp[i],dp[u]+s[make_pair(u+1,i)]);
}
}
printf("%d",n-dp
);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: