zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    CodeForcesGym 100524A Astronomy Problem
    ZOJ 2567 Trade
    HDU 3157 Crazy Circuits
    CodeForcesGym 100212E Long Dominoes
    UVALive 6507 Passwords
    [转]
    java socket
    Spark RDD Operations(2)
    Spark cache 和 persist
    vim 基础命令
  • 原文地址:https://www.cnblogs.com/qt666/p/7328154.html
Copyright © 2011-2022 走看看