[POJ3274] Gold Balanced Lineup

来源:互联网 发布:mysql最大连接数 编辑:程序博客网 时间:2024/05/21 19:33

题目

给出长度为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  23333LLint 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;}
原创粉丝点击