P1114 “非常男女”计划
题意:给你一个01串,求满足0和1总数相等的最大字串
$n\ \le\ 10^5$
1、$O(n^3)$枚举起点终点,统计判断是否成立
2、$O(n^2)$先$O(n)$时间计算01个数的前缀和,然后$O(1)$统计
然而
以上两种做法都会TLE
不难发现,对于算法2,判断成立的条件是$sum1[j]-sum1[i]==sum0[j]-sum0[i]$
可以变个形$sum1[j]-sum0[j]==sum1[i]-sum0[i]$
我们令$cha[i]=sum1[i]-sum0[i]+n$(加n是为了防止出现负数)
那么现在,对于cha数组,我们只需要找出两个距离最远的相同数字就行了!
分别维护每个数字出现的最左和最右,$O(n)$取max
#include<cstdio> #include<iostream> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define olinr return #define _ 0 #define love_nmr 0 #define DB double inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-f; ch=getchar(); } while(isdigit(ch)) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } inline void put(int x) { if(x<0) { x=-x; putchar('-'); } if(x>9) put(x/10); putchar(x%10+'0'); } int n; int ls[505000]; int rs[505000]; int su1[105000]; int su2[105000]; int cha[105000]; int minn=0x7fffffff; int maxx; int main() { n=read(); for(int x,i=1;i<=n;i++) { x=read(); if(!x) { su1[i]=su1[i-1]+1; su2[i]=su2[i-1]; } else { su1[i]=su1[i-1]; su2[i]=su2[i-1]+1; } cha[i]=su1[i]-su2[i]+n; } memset(ls,0x6f,sizeof ls); for(int i=1;i<=n;i++) { ls[cha[i]]=min(ls[cha[i]],i); rs[cha[i]]=max(ls[cha[i]],i); minn=min(minn,cha[i]); maxx=max(maxx,cha[i]); } int ans=0; for(int i=minn;i<=maxx;i++) { if(i==n) ans=max(ans,rs[i]); else ans=max(ans,rs[i]-ls[i]); } put(ans); olinr ~~(0^_^0)+love_nmr; }
----olinr