Luogu_P2519 [HAOI2011]problem a【题解】DP

题面:https://www.luogu.org/problem/P2519

题面真简单

设这个人的名次为他前面的人数加1。

那么我们可以知道n-bi-ai就是并列的人数。

设l为ai+1设r为n-bi。

那么并列人数就是r-l+1。

那么自然就是求若干的不相交的段,使他们的价值和最大。

设fi为到i的最大的价值和。

f[i]=max(f[i-1],f[now]+v[i]);

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
struct node{
    int l,r,v;
}a[maxn],b[maxn];
int cnt,n,tot,f[maxn];
inline bool cmp1(node x,node y){return x.l==y.l ? x.r<y.r : x.l<y.l ;}
inline bool cmp2(node x,node y){return x.r==y.r ? x.l<y.l : x.r<y.r ;}
inline int erf(int l,int r,int d){
    while(l<=r){
        int mid=(l+r)>>1;
        if(a[mid].r<d) l=mid+1;
        else r=mid-1;
    }
    return r;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int x,y;scanf("%d%d",&x,&y);
        a[i].l=x+1;a[i].r=n-y;
    }
    sort(a+1,a+1+n,cmp1);
    for(int i=1;i<=n;i++) if(a[i].l<=a[i].r) b[++tot]=a[i];
    for(int i=1;i<=tot;i++)
        if(i==1 || b[i].l !=b[i-1].l || b[i].r!=b[i-1].r) a[++cnt]=b[i],a[cnt].v=1;
        else if(a[cnt].v<a[cnt].r-a[cnt].l+1) a[cnt].v++;
    sort(a+1,a+1+cnt,cmp2);
    f[1]=a[1].v;
    for(int i=2;i<=cnt;i++){
        int now=erf(1,i-1,a[i].l);
        f[i]=max(f[i-1],f[now]+a[i].v);
    }
    printf("%d
",n-f[cnt]);
    return 0;
}
原文地址:https://www.cnblogs.com/ChrisKKK/p/11589023.html