[POJ3274] Gold Balanced Lineup

題目

給出長度爲N 的序列,尋找最大區間使得區間中數字每個二進制位上的1 的加和相等。

題解

比較容易想到,可以用前綴和+差分求解。
以樣例爲例

序號   數字  二進制   向上前綴和    向左差分
 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章