bzoj2298 [HAOI2011]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

 

正解:$dp$+树状数组优化。

对于每一个人,我们可以求出他的分数表示的排名范围:$[1+a,n-b]$。

那么我们可以把最少说慌的人转化成最多说实话的人,如果两个人的区间相交且不重合,那么他们两人必定有一人说谎。如果相同区间的人数超过了区间长度,那么多于区间长度的那些人必定说谎了,也直接去掉就行了。

把重合的区间合并起来,那么我们的问题变成了求带权的最大不相交区间数,这是一个经典的$dp$,可以用树状数组优化。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <set>
13 #define N (100010)
14 #define il inline
15 #define RG register
16 #define ll long long
17 #define lb(x) (x & -x)
18 
19 using namespace std;
20 
21 struct data{ int l,r,v; }q[N],s[N];
22 
23 int f[N],c[N],n,cnt,ans;
24 
25 il int gi(){
26   RG int x=0,q=1; RG char ch=getchar();
27   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
28   if (ch=='-') q=-1,ch=getchar();
29   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
30   return q*x;
31 }
32 
33 il int cmp(const data &a,const data &b){
34   if (a.l==b.l) return a.r<b.r; return a.l<b.l;
35 }
36 
37 il int cmpr(const data &a,const data &b){ return a.r<b.r; }
38 
39 il void update(RG int x,RG int v){
40   for (;x<=n;x+=lb(x)) c[x]=max(c[x],v); return;
41 }
42 
43 il int query(RG int x){
44   RG int res=0; for (;x;x-=lb(x)) res=max(res,c[x]); return res;
45 }
46 
47 int main(){
48 #ifndef ONLINE_JUDGE
49   freopen("a.in","r",stdin);
50   freopen("a.out","w",stdout);
51 #endif
52   n=gi();
53   for (RG int i=1,a,b;i<=n;++i) a=gi(),b=gi(),q[i]=(data){1+a,n-b};
54   sort(q+1,q+n+1,cmp),q[n+1].l=-1;
55   for (RG int i=1,res=1;i<=n;++i){
56     if (q[i].l>q[i].r || q[i].l<0 || q[i].r>n){ res=1; continue; }
57     if (q[i].l!=q[i+1].l || q[i].r!=q[i+1].r)
58       s[++cnt]=(data){q[i].l,q[i].r,min(q[i].r-q[i].l+1,res)},res=1; else ++res;
59   }
60   sort(s+1,s+cnt+1,cmpr);
61   for (RG int i=1;i<=cnt;++i)
62     f[s[i].r]=max(f[s[i].r],s[i].v+query(s[i].l-1)),update(s[i].r,f[s[i].r]),ans=max(ans,f[s[i].r]);
63   printf("%d\n",n-ans); return 0;
64 }

 

posted @ 2017-08-12 22:32  wfj_2048  阅读(144)  评论(0编辑  收藏  举报