zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    170325 第六章应用层 域名系统 DNS
    文件操作(Linux系统调用)
    进程优先级,进程nice值和%nice的解释
    常用的操作系统进程调度算法
    fork函数返回值问题
    进度条的实现
    find命令
    单链表的插入排序
    B树
    排序
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11589023.html
Copyright © 2011-2022 走看看