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;
}