ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低。”问最少有几个人没有说真话(可能有相同的分数)

Input

第一行一个整数n,接下来n行每行两个整数,第i+1行的两个整数分别代表ai、bi

Output

一个整数,表示最少有几个人说谎

每个人的表述等价于排名[ai+1,n-bi]的人分数相同且区间外的人分数不同

将相同的区间合并并记录个数作为权值,若个数超过区间长度则以区间长度为准

于是问题转化为取一些互不相交的区间使权值和最大,可以dp解决,用树状数组优化可做到O(nlogn)

#include<cstdio>
#include<algorithm>
struct seg{
    int l,r,t;
}ss[100005];
inline bool operator<(const seg&a,const seg&b){
    return a.r!=b.r?a.r<b.r:a.l<b.l;
}
int n,p=0;
int bit[100005];
inline void maxs(int&a,int b){if(a<b)a=b;}
inline void ins(int w,int x){
    ++w;
    while(w<=n+1)maxs(bit[w],x),w+=w&-w;
}
inline int find(int w){
    ++w;
    int ans=0;
    while(w)maxs(ans,bit[w]),w-=w&-w;
    return ans;
}
int main(){
    scanf("%d",&n);
    for(int i=0,l,r;i<n;i++){
        scanf("%d%d",&l,&r);
        ++l;r=n-r;
        if(l<=r)ss[p++]=(seg){l,r,1};
    }
    std::sort(ss,ss+p);
    int p2=0;
    for(int i=1;i<p;i++){
        if(ss[i].l==ss[p2].l&&ss[i].r==ss[p2].r)++ss[p2].t;
        else ss[++p2]=ss[i];
    }
    p=p2+1;
    for(int i=0;i<p;i++){
        int c=ss[i].r-ss[i].l+1;
        if(ss[i].t>c)ss[i].t=c;
    }
    int ans=0;
    for(int i=0;i<p;i++){
        int c=ss[i].t+find(ss[i].l-1);
        maxs(ans,c);
        ins(ss[i].r,c);
    }
    printf("%d\n",n-ans);
    return 0;
}

 

posted on 2016-05-14 22:47  nul  阅读(431)  评论(0编辑  收藏  举报