[BZOJ2298]problem a

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 }

猜你喜欢

转载自www.cnblogs.com/Slrslr/p/10032172.html