problem a题解

problem a题解

分析:

根据成绩比他高的人数\(a_{i}\)和比他低的人数\(b_{i}\)可以推出他的排名区间\([l_{i},r_{i}],\)

其中\(l_{i}=b_{i}+1,r_{i}=n-a_{i}\)

\([l_{i},r_{i}]\)的人成绩一定相等,并与除此区间外的人的成绩都不相同

显然,\(l_{i}>r_{i}\)的人一定在说谎,

并且与\([l_{i},r_{i}]\)有交集或者被其包含的区间与其矛盾

为什么?

若另一区间为\([l_{j},r_{j}]\),设排序后的成绩数组为\(c\)

则意味着

\(c[l_{j}]!=c[l_{j}-1],c[r_{j}]!=c[r_{j}+1]\),

1.显然与和\([l_{i},r_{i}]\)有交集矛盾;

2.因为被包含,

\(c[l_{i}]=c[l_{i}+1]=c[l_{i}+2]=……=c[l_{j}]=c[l_{j}+1]=c[l_{j}+2]=……=c[r_{j}]=……=c[r_{i}]\)

也矛盾。

只有\(l_{i}=l_{j},r_{i}=r_{j}\)时才可合并(数量不能超过区间长度\(r_{i}-l_{i}+1\))

题意:

转换一下题意:

求最少说谎的人数,

等于\(n-\)最多合法的区间数目

区间相交和区间包含不合法,

即是求不相交的最大区间数目(相同的也要算)

操作:

\(r_{i}\)排序,每次取\(<l_{i}\)的区间最大值,

自己的值为最大值+相同的区间数目,

也存在\(r_{i}\)处,

我用的是树状数组维护最大值,

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100006;
int n,num=0,tot=0,t1,t2,f[N],w[N];
struct xd{int l,r;}a[N],b[N];
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
bool cmp(xd u,xd v){
    if(u.r<v.r) return 1;
    if(u.r>v.r) return 0;
    return u.l<v.l;
}//读入优化
inline int lowbit(int x){return x&(-x);}
void add(int u,int v){for(int i=u;i<=n;i+=lowbit(i)) f[i]=max(f[i],v);}
int getmax(int u){
    int maxans=0;
    for(int i=u;i;i-=lowbit(i)) maxans=max(maxans,f[i]);
    return maxans;
}//取最大值
int main(){
    n=read();
    for(int i=1;i<=n;++i){
        t1=read(),t2=read(),t1=n-t1,t2=t2+1;
        if(t1<t2) continue;
        //除去l>r的区间
        a[++num].l=t2,a[num].r=t1;
    }
    sort(a+1,a+num+1,cmp);
    for(int i=1;i<=num;++i){
        if(a[i].l==a[i-1].l&&a[i].r==a[i-1].r) w[tot]=min(b[tot].r-b[tot].l+1,w[tot]+1);
        else w[++tot]=1,b[tot]=a[i];
    }
    //除去完全相同的区间,权值累加
    for(int i=1;i<=tot;++i) t1=getmax(b[i].l-1)+w[i],add(b[i].r,t1);
    //树状数组动态维护
    printf("%d\n",n-getmax(n));
    return 0;
} 
posted @ 2019-08-15 17:01  lsoi_ljk123  阅读(106)  评论(0编辑  收藏  举报