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 }

 

posted @ 2017-10-07 01:01  Leohh  阅读(264)  评论(0编辑  收藏  举报