E. Iva & Pav

https://codeforces.com/problemset/problem/1878/E

题意:给定长度为n的数组,然后q个询问,每次询问给出两个数l和k,l表示数组下标,需要找到一个最大的下标r,使得[l, r]的&结果>=k。

思路:维护一个bit数组,表示当前位置上bit位连续存在的长度。对于每个查询l跟k,从高位到低位考虑当前l上所有的bit位,考虑的过程中维护三个变量ans,len和biglen。ans表示在k的最高位出现之前,当前位置的&运算最长的长度。len表示所有与k重合的bit位中,能&运算的最长长度。 biglen包含了len和k不存在,但是当前位置存在bit位可以运算到的最长长度,然后根据条件来维护变量,最后取最优值即可。

总结:一开始只考虑了ans和len两种情况,没考虑到当前位置跟k的最高位重合,但是后面某个高位当前位置存在,而k不存在的情况。
稀里糊涂的就ac了,本来都打算寄了。。

inline void solve() {
    int n;
    cin >> n;

    vector<int> a(n);
    for (auto& x : a) {
        cin >> x;
    }


    vector<vector<int>> v{n + 1, vector<int>(32, 0)};
    for (int i = n - 1; i >= 0; --i) {
        for (int j = 0; j < 31; ++j) {
            if (a[i] & (1 << j)) {
                v[i][j] = v[i + 1][j] + 1;
            }
        }
    }

    int q;
    cin >> q;

    while (q --) {
        int k, l;
        cin >> l >> k;
        l --;
        bool ok = true;
        int len = 0;
        int ans = 0;
        bool bigger = false;
        int biglen = 0;
        for (int j = 30; j >= 0; --j) {
            if (ok) {
                if (!(k & (1 << j))) {
                    ans = max(ans, v[l][j]);
                }
                else {
                    ok = false;
                    if (!v[l][j]) {
                        len = 0;
                        break;
                    }
                    len = v[l][j];
                }
            }
            else if (k & (1 << j)) {
                if (!bigger && !v[l][j]) {
                    len = 0;
                    break;
                }
                len = min(len, v[l][j]);
            }
            else if (v[l][j]) {
                bigger = true;
                biglen = max(biglen, min(v[l][j], len));
            }
        }
        if (len || ans || biglen) {
            cout << l + max({biglen, ans, len}) << ' ';
        }
        else {
            cout << "-1 ";
        }
    }
    cout << '\n';

}
posted @ 2025-07-02 10:01  _Yxc  阅读(9)  评论(0)    收藏  举报