1. 程式人生 > >bzoj2298 [HAOI2011]problem a

bzoj2298 [HAOI2011]problem a

space std div int include tput name 次數 urn

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

bzoj2298 [HAOI2011]problem a