1. 程式人生 > >CF873B Balanced Substring

CF873B Balanced Substring

1到n內0,1個數相同的個數的最長字串
\(i>=j\)
\[1的個數=0的個數\]
\[sum[i]-sum[j-1]=i-(j-1) - (sum[i]-sum[j-1])\]
這裡把\((j-1)\)替換為\(j\)
\[2*sum[i]-2*sum[j]=i-j\]
\[2*sum[i]-i=2*sum[j]-j\]
列舉i,然後求前面和\(2*sum[i]-i\)相同的最小標號
這裡可能有負數,所以map就好了
當然,因為\(2*sum[i]-i\)的值是在區間[-n,n]的
所以你可以直接+n用陣列桶一下
不告訴你我寫過線段樹

#include <bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn=1e5+7;
const int inf=0x3f3f3f3f;
int n,a[maxn],sum[maxn];
//map<int,int> mi;
int mi[maxn*2];
int main()
{
    scanf("%d",&n);
    FOR(i,1,n) scanf("%1d",&a[i]),sum[i]=sum[i-1]+a[i];
    int ans=0;
    memset(mi,inf,sizeof(mi)); 
    mi[n]=0;
    FOR(i,1,n) {
        int tmp=n+2*sum[i]-i;
        int zz=mi[tmp];
//      if(!zz&&tmp!=0) zz=inf,mi[tmp]=inf;
        ans=max(i-zz,ans);
        mi[tmp]=min(zz,i);
    }
    cout<<ans;
    return 0;
}