题意:n个人,每个人都说剩下人中比自己分数高的人有ai个,比自己分数低的有bi个,问最少有多少人说谎。题中允许同分人出现。
题解:我们可以这么考虑,在所有人中,当前人的排名是[ai+1,n-bi]。在一个合法的情况下,任意两个人的区间是不能相交的。对于一对(i,j),可能会出现ai=aj,bi=bj.所以每个区间相当于有一个权值,代表这个选择这个区间的能带来多少人没有说谎。最后题目就转化成1-n的区间内,选择一些不相交区间使得区间权值和最大。(注意考虑区间的权值不能大于区间长度)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+5; int n,l,r,tot; map<pair<int,int>, int >mp; struct node{ int l,r; bool operator<(const node a)const{ if (r!=a.r)return r<a.r; else return l<a.l; } }p[maxn]; int dp[maxn]; int main() { scanf("%d",&n); for (int i=1;i<=n;i++){ scanf("%d%d",&l,&r); if (l+r>=n)continue; int a=l+1,b=n-r; mp[make_pair(a,b)]++; if (mp[make_pair(a,b)]==1)p[++tot]={a,b}; } sort(p+1,p+tot+1); int nowp=1; for (int i=1;i<=n;i++){ dp[i]=dp[i-1]; while (nowp<=tot&&i>=p[nowp].r){ dp[i]=max(dp[i],dp[p[nowp].l-1]+min(p[nowp].r-p[nowp].l+1,mp[make_pair(p[nowp].l,p[nowp].r)])); nowp++; } } cout<<n-dp[n]<<endl; return 0; }