• [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 - f[n]);
        return 0;
    }
  • 相关阅读:
    九度oj 题目1051:数字阶梯求和
    九度oj 题目1472:求两个多项式的和
    九度oj 题目1173:查找
    九度oj 题目1447:最短路
    九度oj 题目1104:整除问题
    [Luogu] 维护序列
    [Luogu] 计算系数
    [Luogu] 聪明的质监员
    [Luogu] Mayan游戏
    [Luogu] 选择客栈
  • 原文地址:https://www.cnblogs.com/BriMon/p/9439005.html
Copyright © 2020-2023  润新知