zoukankan      html  css  js  c++  java
  • p2519 [HAOI2011]problem a

    传送门

    分析

    其实我们可以很巧妙的把这道题转化成一道线段覆盖的问题,怎么转化呢?
    对于每一个描述,我们可以根据他所描述的比他高的和比他矮的人数来构造一条线段,左端点l即为y+1,右端点r为n-x。
    当我们转化成线段以后,这一段线段就表示着分数相同的人数,那么显然,只有与这个线段完全重合的线段是符合要求的,对于有交集的线段一定是有一个说谎的,但是对于完全重合的线段,还是有可能出现说谎的情况,因为,当完全重合的线段的数量大于这个线段的长度时,就有num-len个人说谎。
    这样我们就可以把这个问题转化成一个线段覆盖的问题了,我们只需要求出有多少重合的线段,那么这个线段的权值就是这个数。然后我们再做带权值的线段覆盖就好了。
    至于怎么在O(n+n*log(n))的时间内做出来呢:先按照右端点排序,然后从前向后枚举每一个线段,用f数组记录在当前坐标时能取到的最大值:f[a[i].r]=f[a[i].l-1]+a[i].v;
    至于为什么是f[a[i].l-1]呢?因为由于这个问题的特殊性,可能会出现[x,x]这种线段,所以为了避免比较麻烦的问题,就这样处理了。再做的时候还需要一直维护着f数组,我们用一个now变量,一直跟着右端点走,总共用O(n)的时间来维护f数组。
    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    struct node {
        int le,ri;
    };
    node a[100100];
    int dp[100100];
    inline bool cmp(const node x,const node y){
        if(x.ri==y.ri)return x.le<y.le;
        return x.ri<y.ri;
    }
    int main(){
        int n,m=0,i,j,k,maxn=0,wh=0,now=0,x,y;
        scanf("%d",&n);
        for(i=1;i<=n;i++){
          scanf("%d%d",&x,&y);
          if(x+y>=n)wh++;
            else a[++m].le=y+1,a[m].ri=n-x;
        }
        sort(a+1,a+m+1,cmp);
        for(i=1;i<=m;i++){
          int sum=1;
          while(a[i+1].le==a[i].le&&a[i+1].ri==a[i].ri)sum++,i++;
          sum=min(sum,a[i].ri-a[i].le+1);
          dp[a[i].ri]=dp[a[i].le-1]+sum;
          while(now<=a[i].ri)
            maxn=max(dp[now],maxn),dp[now]=maxn,now++;
          if(now==a[i].ri+1)now--;
          if(i!=m&&a[i].ri<a[i+1].le)
            while(now<=a[i+1].le)dp[now]=maxn,now++;
          if(now==a[i+1].le+1)now--;
        }
        cout<<n-maxn;
        return 0;
    }
  • 相关阅读:
    知道回答C语言中如何返回值为数组
    指向字符串的指针和char类型的数组
    vba--将excel单元格格式改为常规格式
    vba--分拆工作薄
    VBA-合并多个工作簿
    使用sqlcel导入数据时出现“a column named '***' already belongs to this datatable”问题的解决办法
    使用Sqlcel操作数据库整理数据视频
    SQLCel匹配原数据信息,更新原数据所有信息并插入新数据的过程
    计算订单签收率的sql查询思路与过程(涉及百分比和四舍五入)
    sqlCel查询一个表中部分字段的数据后插入到另一个表中
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/10353065.html
Copyright © 2011-2022 走看看