• bzoj 2298: [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

    Source

    首先我们需要对问题进行一下转化。。。

    一个人有a个人比他分高,b个人比他分低。

    如果他说的是对的,那么排名[a+1,n-b]的人的分数是相同的,且这些人与其他人的分数都不同。。。

    题目问说谎的人最少有多少,那么变为说真话的最多有多少,然后用n减去即可。。。

    那么一个人说的话可以看做一个带权区间,那么我们就是要求出能选出多少个不相交的区间,使得这些区间的权最大。。。

    (因为区间相交表示有更多的人分数相同,显然至少有一个人说了假话。。。)

    dp的话枚举右端点,然后把以该点为右端点的线段dp一下,用了Map nlogn

    // MADE BY QT666
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<map>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int N=100050;
    map<pair<int,int>,int> Map;
    vector<int> p[N];
    int dp[N],n;
    int main(){
      scanf("%d",&n);
      for(int i=1;i<=n;i++){
        int a,b;scanf("%d%d",&a,&b);
        int l=a+1,r=n-b;
        if(l>r) continue;
        Map[make_pair(l,r)]++;
        if(Map[make_pair(l,r)]==1) p[r].push_back(l);
      }
      for(int i=1;i<=n;i++){
        dp[i]=dp[i-1];
        for(int j=0;j<p[i].size();j++){
          int k=p[i][j];
          dp[i]=max(dp[i],dp[k-1]+min(Map[make_pair(k,i)],i-k+1));
        }
      }
      printf("%d
    ",n-dp[n]);
      return 0;
    }
    

      

  • 相关阅读:
    UVa 116 单向TSP(多段图最短路)
    POJ 1328 Radar Installation(贪心)
    POJ 1260 Pearls
    POJ 1836 Alignment
    POJ 3267 The Cow Lexicon
    UVa 1620 懒惰的苏珊(逆序数)
    POJ 1018 Communication System(DP)
    UVa 1347 旅行
    UVa 437 巴比伦塔
    UVa 1025 城市里的间谍
  • 原文地址:https://www.cnblogs.com/qt666/p/7328154.html
Copyright © 2020-2023  润新知