Description
一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低。”问最少有几个人没有说真话(可能有相同的分数)
Input
第一行一个整数n,接下来n行每行两个整数,第i+1行的两个整数分别代表ai、bi
Output
一个整数,表示最少有几个人说谎
Sample Input
3
2 0
0 2
2 2
Sample Output
1
HINT
100%的数据满足: 1≤n≤100000 0≤ai、bi≤n
首先我们考虑一下,撒谎的人去哪了
然后经过周密的推理分析,可以发现,他们爱去哪去哪跟我们半毛钱关系没有
所以我们直接不管他,一开始把不符合条件的直接判掉
然后对于一个人暂时符合条件的人,可以发现它跟其他人的人物关系可以表示成这样
红色表示和我一样的,黄色表示比我弱的,蓝色表示比我强的
可以发现“和我一样的”这个区间一定是不交的
然后我们就相当于要找一些不交的区间使个组最多
用线段树维护一下即可
代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<map>
5 #define ls node<<1
6 #define rs node<<1|1
7 #define M 100010
8 using namespace std;
9 map<int,int>MP[M];
10 int n,cnt,ans;
11 int f[M],val[M<<2];
12 struct point{int l,r,v;}a[M];
13 bool cmp(point a1,point a2) {
14 return a1.l<a2.l||(a1.l==a2.l&&a1.r<a2.r);
15 }
16 void insert(int node,int l,int r,int p,int v) {
17 val[node]=max(val[node],v);
18 if(l==r) return;
19 int mid=(l+r)/2;
20 if(p<=mid) insert(ls,l,mid,p,v);
21 else insert(rs,mid+1,r,p,v);
22 }
23 int query(int node,int l,int r,int l1,int r1) {
24 if(l1<=l&&r1>=r) return val[node];
25 int mid=(l+r)/2,ans=0;
26 if(l1<=mid) ans=max(ans,query(ls,l,mid,l1,r1));
27 if(r1>mid) ans=max(ans,query(rs,mid+1,r,l1,r1));
28 return ans;
29 }
30 int main() {
31 scanf("%d",&n);
32 for(int i=1,l,r;i<=n;i++) {
33 scanf("%d%d",&l,&r);l=l+1,r=n-r;
34 if(l>r) continue;
35 if(!MP[l][r]) MP[l][r]=++cnt,f[cnt]++,a[cnt]=(point){l,r,0};
36 else f[MP[l][r]]++;
37 }
38 for(int i=1;i<=cnt;i++) a[i].v=min(f[i],a[i].r-a[i].l+1);
39 sort(a+1,a+1+cnt,cmp);
40 for(int i=1;i<=cnt;i++) {
41 int t=0;
42 if(a[i].l>1) t=query(1,1,n,1,a[i].l-1);
43 insert(1,1,n,a[i].r,t+a[i].v);
44 ans=max(ans,t+a[i].v);
45 }
46 printf("%d\n",n-ans);
47 return 0;
48 }