最近刚讲了最短路,说要考试我以为是考最短路,然而只有一道是最短路...

  数据似乎有一点问题,不管了,反正手工测评都是对的,那现在就来看看题吧。

 

  Balanced:(此处并没有网址)

  题意概述:$n$  $(n<=50,000)$头牛排成一排,给定每头牛的位置,有两种种族,选出一个尽量长的区间使得这个区间内两种牛的数量相等。

  首先可以想到枚举...前缀和...然而还是$O(N^2)$的复杂度,很显然是过不了的。思考一下前缀和的做法,用两个数组分别表示两种牛数量的前缀和。当$a[j]-a[i-1]=b[j]-b[i-1]$时,$x[j]-x[i]$就是一个合法的答案了。那对这个式子进行移项:$a[j]-b[j]=a[i-1]-b[i-1]$,所以可以再开一个数组表示$x[i]=a[i]-b[i]$,如果两个位置的$x$相同,就是一个合法的答案,而且区间越长答案一定更优,所以只需要保存每个$x$出现的第一次和最后一次位置,统计答案时取max就可以了。注意$x$数组可以出现负数,所以将整个数组同时加上$n$就可以避免负数了。

  
 1 // shzr
 2 
 3 # include <cstdio>
 4 # include <iostream>
 5 # include <algorithm>
 6 # include <cstring>
 7 
 8 using namespace std;
 9 
10 const int maxn=50009;
11 int n,s1[maxn],s2[maxn],ans,x[maxn],minn[maxn*3],maxx[maxn*3];
12 struct co
13 {
14     int id,x;
15 }a[maxn];
16 bool cmp(co a,co b)
17 {
18     return a.x<b.x;
19 }
20 
21 int main()
22 {
23     scanf("%d",&n);
24     memset(minn,127,sizeof(minn));
25     for (int i=1;i<=n;++i)
26         scanf("%d%d",&a[i].id,&a[i].x);
27     sort(a+1,a+1+n,cmp);
28     minn[0]=0;
29     for (int i=1;i<=n;++i)
30     {
31         if(a[i].id==0) s1[i]++;
32         if(a[i].id==1) s2[i]++;
33         s1[i]+=s1[i-1];
34         s2[i]+=s2[i-1];
35         x[i]=s1[i]-s2[i];
36         minn[ x[i]+n+2 ]=min(minn[ x[i]+n+2 ],i);
37         maxx[ x[i]+n+2 ]=max(maxx[ x[i]+n+2 ],i);
38     }
39     for (int i=0;i<=2*n+2;++i)
40     {
41         if(maxx[i]==0||minn[i]>n) continue;
42         if(maxx[i]==minn[i]) continue;
43         ans=max(ans,a[ maxx[i] ].x-a[ minn[i]+1 ].x);
44     }
45     printf("%d",ans);
46     return 0;
47 }
Balanced

相关文章: