[dp][贪心] Jzoj P2519 problem a
题目描述
一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低。”问最少有几个人没有说真话(可能有相同的分数)
输入输出格式
输入格式:
第一行一个整数n,接下来n行每行两个整数,第i+1行的两个整数分别代表ai、bi
输出格式:
一个整数,表示最少有几个人说谎
输入输出样例
说明
100%的数据满足: 1≤n≤100000 0≤ai、bi≤n
题解
- 答案可以转换为n-最多将真话的人
- 设f[i]为前i个人中说真话的人的最多人数,转移显然
- 假设现在做到第j个,要使i~j中的人的分数都相等(因为如果还有更小的话早就处理了)
- 那f[i]=f[j-1]+sum[j][i](j<=i),求这个sum数组可以用map来做
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <map> 4 #include <vector> 5 using namespace std; 6 int n,f[100010]; 7 vector<int>l[100010]; 8 map<pair<int,int>,int>s; 9 int main() 10 { 11 scanf("%d",&n); 12 for (int i=1,x,y;i<=n;i++) 13 { 14 scanf("%d%d",&x,&y); 15 x++,y=n-y; 16 if (x>y) continue; 17 if (++s[make_pair(x,y)]==1) l[y].push_back(x); 18 } 19 for (int i=1;i<=n;i++) 20 { 21 f[i]=f[i-1]; 22 for (int j=0;j<l[i].size();j++) f[i]=max(f[i],f[l[i][j]-1]+min(i-l[i][j]+1,s[make_pair(l[i][j],i)])); 23 } 24 printf("%d",n-f[n]); 25 }