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

 

思路: 这个题目可以转换为给你n个区间,每个区间都有一个价值v,从中选出若干个不相交的区间,使得价值之和最大。每个区间的价值在这里就是有几个重合的区间,如果重合的次数多于区间的长度,那么价值只能是区间的长度,否则就按照实际重合的长度统计。

例如,第一个的名次范围是3到6,第二个人的名字范围是3到6,那么3到6的重合次数就是2,3到6的区间的价值就是2。 明显的,我们选出的这些区间不能是相交的,否则肯定是矛盾的。 由于n有10万,我们可以贪心或者dp解决。

 

 1 #include<bits/stdc++.h>
 2 using namespace std; 
 3 #define rep(i,a,b) for(int i=a;i<=b;i++) 
 4 #define Rep(i,a,b) for(int i=a;i>=b;i--) 
 5 #define ms(i,a)    memset(a,i,sizeof(a))  
 6 #define gc()       getchar() 
 7 template<class T>void read(T &x){
 8     x=0; char c=gc(); 
 9     while (!isdigit(c))  c=gc(); 
10     while (isdigit(c)) x=x*10+(c^48),c=gc(); 
11 }
12 int const N=100000+3; 
13 struct seg{ 
14     int x,y,num;  
15     bool operator <(const seg & rhs) const { if(x!=rhs.x) return x<rhs.x; return y<rhs.y;   } 
16 }a[N];  
17 int n,m,f[N];    
18 int main(){
19     read(n); 
20     rep(i,1,n){
21         int x,y; read(x); read(y);  
22         if(x+y<n){
23             m++;  
24             a[m].x=x+1;  
25             a[m].y=n-y; 
26         } 
27     }
28     sort(a+1,a+m+1); 
29     int cnt=1;  
30     a[1].num=1; 
31     rep(i,2,m) 
32         if(a[i].x==a[cnt].x && a[i].y==a[cnt].y) a[cnt].num++;  
33         else cnt++,a[cnt]=a[i],a[cnt].num=1;  
34     int k=1,r=1,v=0;
35     rep(i,1,cnt) if(a[i].num>a[i].y-a[i].x+1) a[i].num=a[i].y-a[i].x+1;  
36     rep(i,1,n){
37         f[i]=max(f[i],f[i-1]);   
38         int num=0 ; 
39         if(a[k].x!=i || k>cnt) continue; 
40         while (a[k].x==i && k<=cnt ){  
41             while (r<i) v=max(v,f[r]),r++;  
42             f[a[k].y]=max(f[a[k].y],v+a[k].num);  
43             k++;  
44         } 
45     }
46     printf("%d\n",n-f[n]); 
47     return 0; 
48 }
View Code

 

posted @ 2019-03-30 01:17  zjxxcn  阅读(150)  评论(0编辑  收藏  举报