1. 程式人生 > 其它 >Solution -「LOCAL」 二進位制的世界

Solution -「LOCAL」 二進位制的世界

\(\mathcal{Description}\)

  OurOJ.

  給定序列 \(\{a_n\}\) 和一個二元運算 \(\operatorname{op}\in\{\operatorname{and},\operatorname{or},\operatorname{xor}\}\),對於 \(i\in[2,n]\),求出 \(\max_{j\in[1,i)}\{a_i\operatorname{op} a_j\}\) 以及 \(|\arg\max_{j\in[1,i)}\{a_i\operatorname{op} a_j\}|\)

  \(n\le10^5\)\(a_i<2^{16}\)

\(\mathcal{Solution}\)

  也許算是 Meet in Middle?從左到右線上更新可用的 \(a_j\) 資訊並求出對於當前 \(i\) 的答案,維護一個 \(f(u,v)\),表示選取的 \(a_j\) 的高八位是 \(u\)\(a_i\) 的低八位是 \(v\) 時,低八位能得到的最大值以及方案數。那麼更新時,用當前 \(a_j\) 的低八位更新所有 \(f(u,i)\);查詢時列舉高八位選擇的值 \(i\),並用 \(f(i,v)\) 更新答案。最終複雜度為 \(\mathcal O(n\sqrt A)\)

  確實是比較巧妙的複雜度平衡,也是一個實用的 trick√

\(\mathcal{Code}\)

/*~Rainybunny~*/

#include <bits/stdc++.h>

#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )

typedef std::pair<int, int> PII;
#define fi first
#define se second

const int MAXN = 1e5, MAXSV = 1 << 8;
int n, a[MAXN + 5];
char op[5];
PII f[MAXSV][MAXSV];

inline void update( const int x, const auto& opt ) {
    int h = x >> 8, l = x ^ h << 8;
    rep ( i, 0, MAXSV - 1 ) {
        int v = opt( i, l );
        if ( f[h][i].fi < v ) f[h][i] = { v, 1 };
        else if ( f[h][i].fi == v ) ++f[h][i].se;
    }
}

inline PII query( const int x, const auto& opt ) {
    int l = x & ( ( 1 << 8 ) - 1 );
    PII ret( 0, 0 );
    rep ( h, 0, MAXSV - 1 ) if ( f[h][l].se ) {
        int cur = opt( h, x >> 8 ) << 8 | f[h][l].fi;
        if ( ret.fi < cur ) ret = { cur, f[h][l].se };
        else if ( ret.fi == cur ) ret.se += f[h][l].se;
    }
    return ret;
}

inline void solve( const auto& opt ) {
    update( a[1], opt );
    rep ( i, 2, n ) {
        PII ans( query( a[i], opt ) );
        printf( "%d %d\n", ans.fi, ans.se ), update( a[i], opt );
    }
}

int main() {
    scanf( "%d %s", &n, op );
    rep ( i, 1, n ) scanf( "%d", &a[i] );
    if ( op[0] == 'x' ) {
        solve( []( const int u, const int v ) { return u ^ v; } );
    } else if ( op[0] == 'a' ) {
        solve( []( const int u, const int v ) { return u & v; } );
    } else {
        solve( []( const int u, const int v ) { return u | v; } );
    }
    return 0;
}