BZOJ 1637 [Usaco2007 Mar]Balanced Lineup:前缀和 + 差分
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1637
题意:
Farmer John 决定给他的奶牛们照一张合影,他让 N (1 ≤ N ≤ 50,000) 头奶牛站成一条直线,每头牛都有它的坐标x(0 <= x <= 10^9)和种族(0或1)。
他只给一部分牛照相,并且这一组牛的阵容必须是“平衡的”。
平衡的阵容,指的是在一组牛中,种族0和种族1的牛的数量相等。
区间的大小为区间内最右边的牛的坐标减去最做边的牛的坐标。
请算出最广阔的区间,使这个区间内的牛阵容平衡。
题解:
先将所有牛按坐标x从小到大排序。
在id = 0处+1,在id = 1处-1。
sum[i]为第i头牛处的前缀和。
结论:
对于一段牛的0和1数量相等的区间[L,R](L,R为牛的编号),sum[R] = sum[L-1](因为相等数量的+1和-1抵消掉了)。
所以对于每头牛i,右端点为i的最大区间为[j+1,i],其中sum[j] = sum[i]。
用pos数组记录每一种sum值,最早出现的牛的右边的牛的坐标x。
然后扫一遍就好了。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #define MAX_N 100005 6 7 using namespace std; 8 9 struct Cow 10 { 11 int id; 12 int x; 13 Cow(int _id,int _x) 14 { 15 id=_id; 16 x=_x; 17 } 18 Cow(){} 19 friend bool operator < (const Cow &a,const Cow &b) 20 { 21 return a.x<b.x; 22 } 23 }; 24 25 int n; 26 int ans=0; 27 int pos[MAX_N]; 28 int sum[MAX_N]; 29 Cow c[MAX_N]; 30 31 void read() 32 { 33 cin>>n; 34 for(int i=1;i<=n;i++) 35 { 36 cin>>c[i].id>>c[i].x; 37 } 38 } 39 40 void solve() 41 { 42 sort(c+1,c+n+1); 43 memset(pos,-1,sizeof(pos)); 44 sum[0]=0; 45 for(int i=1;i<=n;i++) 46 { 47 sum[i]=sum[i-1]+(c[i].id==0?1:-1); 48 if(pos[sum[i]+n]==-1) pos[sum[i]+n]=c[i+1].x; 49 else ans=max(ans,c[i].x-pos[sum[i]+n]); 50 } 51 } 52 53 void print() 54 { 55 cout<<ans<<endl; 56 } 57 58 int main() 59 { 60 read(); 61 solve(); 62 print(); 63 }