zoukankan      html  css  js  c++  java
  • BZOJ2298 [HAOI2011]problem a

    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

    正解:DP

    解题报告:

      给出了多少个人更高、更低。那么对于每个人都可以得到一个rank的可行区间,可以把给定数据变成一些带权的线段。题目要求最小说谎数,可以先求最多可以有多少人说的是真话。我们需要求出选出一些线段,使得两两不覆盖的最大权值和。

      我们考虑如何确定线段的权值,线段的权值肯定是代表这个线段的重复出现次数。选了这个线段就意味着同时可以满足那么多个人的话。但注意如果次数超过了区间长度显然是不可以的,因为区间最多只能有那么多个人,不可能更多人同分,取一个min就可以了。判重的话我开了个map记了一下。

      DP的话固定右端点,然后对于所有以这个顶点为右端点的线段拿出来DP一下。

     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 #ifdef WIN32   
    14 #define OT "%I64d"
    15 #else
    16 #define OT "%lld"
    17 #endif
    18 using namespace std;
    19 typedef long long LL;
    20 const int MAXN = 100011;
    21 int n,f[MAXN];
    22 map<pair<int,int>,int>mp;
    23 vector<int>pre[MAXN];
    24 
    25 inline int getint()
    26 {
    27        int w=0,q=0;
    28        char c=getchar();
    29        while((c<'0' || c>'9') && c!='-') c=getchar();
    30        if (c=='-')  q=1, c=getchar();
    31        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
    32        return q ? -w : w;
    33 }
    34 
    35 inline void work(){
    36     n=getint(); int x,y,len;
    37     for(int i=1;i<=n;i++) {
    38     x=getint(); y=getint();
    39     x++; y=n-y;//左右端点表示的是rank的可能区间    
    40     if(x>y) continue;
    41     mp[make_pair(x,y)]++;
    42     if(mp[make_pair(x,y)]==1) pre[y].push_back(x);
    43     }    
    44     for(int i=1;i<=n;i++) {
    45     f[i]=f[i-1]; len=pre[i].size();
    46     for(int j=0;j<len;j++) {
    47         //相当于取带权线段不重叠,且权值和最大
    48         //前一位的f加上这一个线段的权值,取min表示要么是这条线段出现次数,要么是线段长度(因为不可能超过区间长度个人说同样的话)
    49         f[i]=max(f[pre[i][j]-1]+min(mp[make_pair(pre[i][j],i)],i-pre[i][j]+1),f[i]);
    50     }
    51     }
    52     printf("%d",n-f[n]);
    53 }
    54 
    55 int main()
    56 {
    57   work();
    58   return 0;
    59 }
  • 相关阅读:
    office2007/2010/2013输入公式的正确方式
    寻找与网页内容相关的图片(三)网易新闻与qq空间的做法
    寻找与网页内容相关的图片(二)reddit的做法
    用matplotlib绘制漫画风格的图表
    Monty Hall悖论
    天气中的概率 | 连续两天的天气独立吗?
    寻找与网页内容相关的图片(一) 开放图谱计划
    识别验证码:寻找数字的位置(三)
    识别验证码:寻找数字的位置(二)
    识别验证码:寻找数字的位置(一)
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5750171.html
Copyright © 2011-2022 走看看