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';
}

浙公网安备 33010602011771号