[BZOJ2298] 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

 


 

 

好吧...其实讲完了我还是不会。

抄的题解2333...
设f[i]表示前i个人最多有多少个人说的是真话。

然后f[i] = max(f[j-1] + sum[j, i]),sum是指排名可能的区间为[l,r]的人的个数。

然后这样转移是O(N^2)的。

但是有不少冗余状态,也就是说,sum[i, j]=0,为结局我这种情况我们可以对每一个r建立一个vector存储对应这个r的l。

然后怎么如果硬开空间的话空间复杂度也是O(N^2)的承受不了, 所以可以用map;

 

 


 

 

 

#include <iostream>
#include <cstdio>
#include <map>
#include <vector>
using namespace std;
inline int read() {
    int res=0;char c=getchar();bool f=0;
    while(!isdigit(c)) {if(c=='-')f=1;c=getchar();}
    while(isdigit(c))res=(res<<3)+(res<<1)+(c^48),c=getchar();
    return f?-res:res;
}
int n;
int f[100005];
map < pair <int, int>, int > sum;
vector <int> p[100005];

int main()
{
    n = read();
    for (register int i = 1 ; i <= n ; i ++) 
    {
        int l = read() + 1, r = n - read();
        if (l > r) continue;
        sum[make_pair(l, r)]++;
        if (sum[make_pair(l, r)] == 1) p[r].push_back(l);
    }
    for (register int i = 1 ; i <= n ; i ++)
    {
        f[i] = f[i-1];
        for (register int j = 0 ; j < p[i].size() ; j ++)
            f[i] = max(f[i], f[p[i][j]-1] + min(sum[make_pair(p[i][j], i)], i - p[i][j] + 1));
    }
    printf("%d\n", n - f[n]);
    return 0;
}

 

 

 

posted @ 2018-08-14 19:13  zZhBr  阅读(81)  评论(0编辑  收藏  举报