zoukankan      html  css  js  c++  java
  • bzoj2298: [HAOI2011]problem a(dp)

    2298: [HAOI2011]problem a

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1472  Solved: 723
    [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

     

    /*
    对于每一个描述,我们可以根据他所描述的比他高的和比他矮的人数来构造一条线段,左端点l即为y+1,右端点r为n-x。 
    当我们转化成线段以后,这一段线段就表示着分数相同的人数,那么显然,只有与这个线段完全重合的线段是符合要求的,
    对于有交集的线段一定是有一个说谎的,但是对于完全重合的线段,还是有可能出现说谎的情况
    所以我们可以写个前向星add(b[i].r,b[i].l?1,b[i].w)
    l为该区间的左端点,r为该区间的右端点,w为权值
    建这个边的原因是f[b[i].r]=max(f[b[i].r],f[b[j].l?1]+e[i].w)
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    #define N 100007
    
    using namespace std;
    int n,tot,num,cnt;
    
    struct node{int l,r,w;}a[N],b[N];
    struct node2{int u,v,net,w;}e[N];
    int f[N],head[N];
    
    int cmp(node a,node b)
    {
        if(a.r==b.r)return a.l<b.l;
        return a.r<b.r;
    }
    int cmp2(node a,node b)
    {
        if(a.r==b.r)return a.w<b.w;
        return a.r<b.r;
    }
    
    void add(int u,int v,int w)
    {
        e[++cnt].v=v;e[cnt].w=w;e[cnt].net=head[u];head[u]=cnt;
    }
    int main()
    {
        
        scanf("%d",&n);int x,y,ans=0;
        memset(head,-1,sizeof(head)),cnt=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            if(x+y>=n){ans++;continue;}
            a[++tot].l=x+1;
            a[tot].r=n-y;
        }
        sort(a+1,a+tot+1,cmp);
        for(int i=1;i<=tot;i++)
        {
            if(a[i].l==a[i-1].l&&a[i].r==a[i-1].r)
            {
                if(b[num].w<b[num].r-b[num].l+1)
                b[num].w++;
            }
            else b[++num].l=a[i].l,b[num].r=a[i].r,b[num].w=1;
        }
        sort(b+1,b+num+1,cmp2);
        for(int i=1;i<=num;i++) add(b[i].r,b[i].l-1,b[i].w);
        int r=0;
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            f[i]=f[i-1];
            for(int j=head[i];j!=-1;j=e[j].net)
            {
                int v=e[j].v;
                f[i]=max(f[i],f[v]+e[j].w);
            }
        }
        printf("%d
    ",n-f[n]);
    }

     

    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    智能指针
    C++学习之对类中的成员函数的定义和声明最后添加一个const作用
    动态链接,静态链接库
    Java 位运算
    Java 工具类
    Java 枚举
    Java 内部类
    Java 异常机制
    Java hashCode 和 equals
    Java 字节流和字符流
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7561925.html
Copyright © 2011-2022 走看看