題目
給出長度爲
題解
比較容易想到,可以用前綴和+差分求解。
以樣例爲例
序號 數字 二進制 向上前綴和 向左差分
1 7 111 1 1 1 0 0
2 6 110 2 2 1 0 -1
3 7 111 3 3 2 0 -1
4 2 010 3 4 2 1 -2
5 1 001 3 4 3 1 -1
6 4 100 4 4 3 0 -1
7 2 010 4 5 3 1 -2
那麼如果出現相同兩行差分相同,就是題目中所謂的“平衡區間”。
如何尋找相同兩行差分我用了雙哈希+排序。
注意要將第0行的差分補上。
代碼
/// by ztx
/// blog.csdn.net/hzoi_ztx
// #include <bits/stdc++.h>
#include <cstdio>
#include <algorithm>
#include <vector>
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define Rev(i,r,l) for(i=(r);i>=(l);i--)
#define rev(i,r,l) for(i=(r);i> (l);i--)
#define Each(i,v) for(i=v.begin();i!=v.end();i++)
#define r(x) read(x)
typedef long long ll ;
typedef double lf ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
if (CH == '-') NEG = true , CH = getchar() ;
while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
if (NEG) ret = -ret ;
}
template <typename TP>inline bool MI(TP&a, const TP&b) { return a>b?a=b,true:false; }
template <typename TP>inline bool MA(TP&a, const TP&b) { return a<b?a=b,true:false; }
using namespace std;
typedef pair<int,int> pii;
typedef pair<pii,int> piii;
#define kN 100002LL
#define kM 32LL
#define P1 233LL
#define P2 23333LL
int n, m, a[kM][kN] = {0}, mi = 0, ans = 0;
vector<piii>v;
piii hash(int i) {
int j, a = 0, b = 0;
rep (j,1,m)
a = a*P1+::a[j][i],
b = b*P2+::a[j][i];
return make_pair(make_pair(a,b),i);
}
int main() {
int i, j, k;
r(n), r(m);
Rep (i,1,n) {
r(k);
Rep (j,1,m)
a[j][i] = k&1, k >>= 1,
a[j][i] += a[j][i-1];
}
Rep (i,1,n) {
rep (j,1,m)
a[j][i] -= a[j+1][i],
MI(mi,a[j][i]);
a[m][i] = 0;
}
mi = -mi;
Rep (j,1,m) Rep (i,0,n) a[j][i] += mi;
Rep (i,0,n) v.push_back(hash(i));
sort(v.begin(),v.end());
i = 0;
rep (j,1,v.size()) {
if (v[j].first == v[i].first) continue;
MA(ans,v[j-1].second-v[i].second);
i = j;
}
MA(ans,v[j-1].second-v[i].second);
printf("%d\n", ans);
END: getchar(), getchar();
return 0;
}