BZOJ 1637: [Usaco2007 Mar]Balanced Lineup (前缀和乱搞)
1637: [Usaco2007 Mar]Balanced Lineup
Time Limit: 5 Sec Memory Limit: 64 MB Submit: 503 Solved: 336 [Submit][Status][Discuss]
Description
Farmer John 决定给他的奶牛们照一张合影,他让 N (1 ≤ N ≤ 50,000) 头奶牛站成一条直线,每头牛都有它的坐标(范围: 0..1,000,000,000)和种族(0或1)。 一直以来 Farmer John 总是喜欢做一些非凡的事,当然这次照相也不例外。他只给一部分牛照相,并且这一组牛的阵容必须是“平衡的”。平衡的阵容,指的是在一组牛中,种族0和种族1的牛的数量相等。 请算出最广阔的区间,使这个区间内的牛阵容平衡。区间的大小为区间内最右边的牛的坐标减去最做边的牛的坐标。 输入中,每个种族至少有一头牛,没有两头牛的坐标相同。
Input
行 1: 一个整数: N 行 2..N + 1: 每行两个整数,为种族 ID 和 x 坐标。
Output
行 1: 一个整数,阵容平衡的最大的区间的大小。
Sample Input
7 0 11 1 10 1 25 1 12 1 4 0 13 1 22
Sample Output
11 输入说明
有7头牛,像这样在数轴上。
1 1 0 1 0 1 1 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 输出说明
牛 #1 (at 11), #4 (at 12), #6 (at 13), #7 (at 22) 组成一个平衡的最大的区间,大小为 22-11=11 个单位长度。
<-------- 平衡的 --------> 1 1 0 1 0 1 1 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
题意:有n头牛,在一个数轴上,没头牛有一个坐标x和性别(0或者1)
现在要选一段最长的连续区间使得区间内公牛和母牛的个数相等(区间的端点必须有牛存在才可以选),问最长区间是多少。
思路:乱搞。先按照x排序。把性别为0的换成-1,这样比较好处理平衡。然后分三种情况,包含左端点,包含右端点,两个端点都不包含。前两种情况随便搞。最后一种情况,我的做法是正反扫两遍预处理出了sum1[i]和sum2[i],sum1[i]表示正向性别和为i的最左端的点的id,sum2[i]表示反向性别和为i的最右端的点的id。
如果所有奶牛的性别和为total,那么对于正向扫的时候,设当前性别的前缀和为X,中间选的奶牛的前缀和为Z,最后不选的奶牛的性别和为Y,那么就有X+Y+Z=total.
我们要使得Z为0,所以Y=total-x. 说白了就是对于从左往右的每个i,找到最右端的某个点使得这两个点中间的奶牛(不包含这两个点)的性别和为0.
注意下标可能为负,所以整体平移一下就好。
然后三种情况取最大值。
时间复杂度O(n)
/* ***********************************************
Author :111qqz
Created Time :2016年04月08日 星期五 13时59分29秒
File Name :code/bzoj/1637.cpp
************************************************ */
1#include <cstdio>
2#include <cstring>
3#include <iostream>
4#include <algorithm>
5#include <vector>
6#include <queue>
7#include <set>
8#include <map>
9#include <string>
10#include <cmath>
11#include <cstdlib>
12#include <ctime>
13#define fst first
14#define sec second
15#define lson l,m,rt<<1
16#define rson m+1,r,rt<<1|1
17#define ms(a,x) memset(a,x,sizeof(a))
18typedef long long LL;
19#define pi pair < int ,int >
20#define MP make_pair
1using namespace std;
2const double eps = 1E-8;
3const int dx4[4]={1,0,0,-1};
4const int dy4[4]={0,-1,1,0};
5const int inf = 0x3f3f3f3f;
6const int N=1E5+7;
7const int C=50000;
8int total;
9int ans;
10int sum1[N],sum2[N];
11int n;
12struct node
13{
14 int sex;
15 int x;
1 bool operator < (node b)const
2 {
3 return x<b.x;
4 }
5}a[N];
int solve()
{
1 //三种情况,
2 int cur = 0;
3 int res2=-1;
4 for ( int i = 1 ;i <= n ; i++)
5 {
6 cur += a[i].sex;
7// cout<<"cur:"<<cur<<endl;
8 if (cur==0)
9 res2 = a[i].x-a[1].x;
10 }
11 int res3 = -1;
12 cur = 0 ;
13 for ( int i = n ; i >= 1 ; i--)
14 {
15 cur +=a[i].sex;
16 if (cur==0)
17 res3 = a[n].x - a[i].x;
18 }
19 ms(sum1,-1);
20 cur = C ;
21 for ( int i = 1 ;i <= n ; i++)
22 {
23 cur += a[i].sex;
24 if (sum1[cur]==-1) sum1[cur] = i;
25 }
26 cur = C;
27 ms(sum2,-1);
28 for ( int i = n ; i >= 1 ; i--)
29 {
30 cur += a[i].sex;
31 if (sum2[cur]==-1) sum2[cur] = i;
32 }
33 int res= 0;
34 cur = C;
35 for ( int i = 1 ; i <= n-1 ; i++)
36 {
37 cur += a[i].sex;
38 int Y = total - cur+C;
39 if (Y>=0&&sum2[Y]!=-1&&a[sum2[Y]-1].x-a[i+1].x>0) res = max(res,a[sum2[Y]-1].x-a[i+1].x);
40 }
1 res = max(res,res2);
2 res = max(res,res3);
3 return res;
4}
5int main()
6{
7 #ifndef ONLINE_JUDGE
8 freopen("code/in.txt","r",stdin);
9 #endif
1 ios::sync_with_stdio(false);
2 cin>>n;
3 total = 0 ;
4 for ( int i = 1 ; i <= n ; i++)
5 {
6 cin>>a[i].sex>>a[i].x;
7 if (a[i].sex==0) a[i].sex--;
8 total += a[i].sex;
9 }
10 total += C;
sort(a+1,a+n+1);
cout<<solve()<<endl;
1 #ifndef ONLINE_JUDGE
2 fclose(stdin);
3 #endif
4 return 0;
5}