标签:统计 += 注意 -- 排序 sam lld 题目 getc
7
0 11
1 10
1 25
1 12
1 4
0 13
1 22
11
输入如下图所示
输出如下图所示
看上面的样例,我们会发现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); }
[USACO2007 MAR]Balanced Lineup
标签:统计 += 注意 -- 排序 sam lld 题目 getc
原文地址:https://www.cnblogs.com/wzx-RS-STHN/p/13049823.html