zoukankan      html  css  js  c++  java
  • 华东交通大学2019年ACM“双基”程序设计竞赛 H-谁在说谎 BZOJ2298 洛谷P2519

    题目链接:https://ac.nowcoder.com/acm/contest/1168/H

    注解代码里有,大致思路就是把输入数据转换成线段,有重复的线段可以累加,但是最大不能超过该线段的长度,然后找出最大的不重合区间,其他没计入的都是说谎的人

    #include<bits/stdc++.h>
    #include<vector>
    #include<map>
    #include<queue>
    #define LL long long
    #define INF 0x3f3f3f3f
    #define MOD 1000000007
    using namespace std;
    int dp[100005];
    struct node
    {
        int l;
        int r;
    }a[100005];
    bool cmp(node x, node y)
    {
        if(x.r == y.r)
            return x.l < y.l;
        else
            return x.r < y.r;
    }
    int main()
    {
        int n, x, y, pos = 1;
        scanf("%d", &n);
        for(int i = 1;i <= n;i++)
        {
            scanf("%d%d", &x, &y);
            if(x+y < n)                         //防止出现负数
            {
                a[pos].l = x+1;                 //求出这个人所在区间
                a[pos].r = n-y;
                pos++;
            }
        }
        sort(a+1, a+pos+1, cmp);                //排序,以右区间为判断条件,小的在前面,右区间相同的左区间小的在前面
        int j = 1, flag = 0;
        for (int i = 1;i <= n;i++)
        {
            dp[i] = dp[i-1];                    //dp记录当前说真话的人数
            while(a[j].r < i)                   //右区间比i小的都是说谎的人
            {
                j++;
                if(j > 100000)                  //当j大于n时跳出循环,否则会段错误
                {
                    flag = 1;
                    break;
                }
            }
            int temp = 0;
            while(a[j].r == i)                  //如果在一个说谎的人之后是数个右区间相同的人,这里会直接从最后一个开始遍历
            {                                   //因为当a[j].r大于i时整个循环只会进行dp数组的传递和i++
                if(a[j].l == a[j-1].l)          //左区间也相同时累加
                    temp++;
                else
                    temp = 1;
                dp[i] = max(dp[i], dp[a[j].l-1] + min(temp, i - a[j].l + 1));//
                j++;             //dp[a[j].l-1]是上一段不重合的区间
            }
            if(flag)                            //前面a[j].r都小于i时j会一直加到100000,此时dp[n]的值是0
            {                                   //所以需要从n开始往前回溯到有值的dp[i]再把值赋给dp[n]
                for(int i = n;i >= 1;i--)
                {
                    if(dp[i])
                    {
                        dp[n] = dp[i];
                        break;
                    }
                }
                break;
            }
        }
        printf("%d
    ", n-dp[n]);
        return 0;
    }

    这道题洛谷,bzoj上面都有,但是华交好像加了几组数据,卡了我好久………没后台数据就是难找bug,还是codeforces好啊

  • 相关阅读:
    结巴分词 0.14 版发布,Python 中文分词库
    Lazarus 1.0.2 发布,Pascal 集成开发环境
    Android全屏 去除标题栏和状态栏
    服务器日志现 Android 4.2 传将添多项新特性
    Percona XtraBackup 2.0.3 发布
    长平狐 Android 强制设置横屏或竖屏 设置全屏
    NetBeans 7.3 Beta 发布,全新的 HTML5 支持
    CppDepend现在已经支持Linux
    GromJS 1.7.18 发布,服务器端的 JavaScript
    Apache OpenWebBeans 1.1.6 发布
  • 原文地址:https://www.cnblogs.com/Mamba0Z/p/11885176.html
Copyright © 2011-2022 走看看