题目
Description
Farmer John 决定给他的奶牛们照一张合影,他让 N (1 ≤ N ≤ 50,000) 头奶牛站成一条直线,每头牛都有它的
坐标(范围: 0..1,000,000,000)和种族(0或1)。一直以来 Farmer John 总是喜欢做一些非凡的事,当然这次照相
也不例外。他只给一部分牛照相,并且这一组牛的阵容必须是“平衡的”。平衡的阵容,指的是在一组牛中,种族
0和种族1的牛的数量相等。请算出最广阔的区间,使这个区间内的牛阵容平衡。区间的大小为区间内最右边的牛的
坐标减去最做边的牛的坐标。输入中,每个种族至少有一头牛,没有两头牛的坐标相同。
坐标(范围: 0..1,000,000,000)和种族(0或1)。一直以来 Farmer John 总是喜欢做一些非凡的事,当然这次照相
也不例外。他只给一部分牛照相,并且这一组牛的阵容必须是“平衡的”。平衡的阵容,指的是在一组牛中,种族
0和种族1的牛的数量相等。请算出最广阔的区间,使这个区间内的牛阵容平衡。区间的大小为区间内最右边的牛的
坐标减去最做边的牛的坐标。输入中,每个种族至少有一头牛,没有两头牛的坐标相同。
Input
* 行 1: 一个整数: N
* 行 2..N + 1: 每行两个整数,为种族 ID 和 x 坐标。
* 行 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
HINT
输入如下图所示
输出如下图所示
思路:
看上面的样例,我们会发现0-10坐标区间内1比0多2个,0-22区间内1比0也多2个;
我们也发现0-10坐标区间内1的个数为2个,0的个数为0个,0-22区间内1个数为4个,0的个数为2个;
这两个区间的0,1个数相减,可以得出11-22区间内0,1的个数,同时我们会发现0和1的个数都为2;
说明 0~x1,0~x2的0,1个数的差值相同,那么说明x1+1~x2的区间内0和1的个数相等;
看起来像是统计前缀,其实也是统计前缀,但用更快的方法不需要直接统计
我们可以先按坐标排序,然后把种族数字为0的改为-1;
从0~x种族数字相加,就可以统计出0~x之间0,1个数的差值;
注意(错误思路,但也看看助于理解)
因为要找区间最大的,所以只把第一次出现0~x1的差值的x1坐标记下;
然后往后找,找一个0~x2的差值与前面出现的差值相等,再x2-x1-1求出区间长度;
但不一定每一个坐标都是有数的,
如 1 1
1 5
0 7
1 1 0
1--5-7--
x1=1, x2=7
x2-x1-1 != 7-5
所以记坐标是不行的;
正确思路
我们就需要记下每个坐标的序号
如 1 4
1 7
坐标4的序号是1,坐标7的序号是2;
那么求出差值相同的坐标0~x1,0~x2中x1,x2的序号y1,y2,再a[y2]-a[y1+1]求出区间长度,即可;
最后用max求出最大区间长度就可以了
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; inline ll read() { ll a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } struct sbbb { ll x,y; }a[500001];//结构体 x 代表每头牛的种族,y 是坐标 ll n,ans,num,f[500001]; inline ll cmp(sbbb a,sbbb b) { return a.y<b.y; }//按坐标从小到大排序 int main() { n=read(); for(ll i=1;i<=n;i++) { a[i].x=read(); a[i].y=read(); if(a[i].x==0) a[i].x=-1;//将每个种族为0的牛,把种族改为-1,方便统计 } sort(a+1,a+n+1,cmp);//排序 for(ll i=1;i<=n;i++) { num+=a[i].x;//计算差值 if(!f[num+n])//记下第一次出现的差值 因为差值可能是负数,所以下标加上n f[num+n]=i;//记下坐标的序号 else ans=max(ans,a[i].y-a[f[num+n]+1].y);//统计最大区间长度 } printf("%lld",ans); }