We can, for each bit, calculate the prefix sums of the array ( $ pref[i][j] $ is the number of occurrences of the $ j $ -th bit in the first $ i $ elements of the array. This can be calculated in $ \mathcal{O}(n \log(max(a))) $ . We know that if $ pref[r][j] − pref[l − 1][j] = r − l + 1 $ , then the $ j $ -th bit is present in all elements of the subsegment [ $ l, r $ ] of the array $ a $ , which means the value of $ f(l, r) $ is equal to the sum of all bits for which this condition is true on the subsegment from $ l $ to $ r $ , and we can calculate that in $ \mathcal{O}(\log(max(a))) $ .
Next, for each query, we can use binary search to find $ r $ , by calculating $ f(l, mid) $ . If $ f(l, r) \ge k $ then we found an index for which the condition is true, so we move the left to $ mid + 1 $ , else we move the right to $ mid-1 $ . This solution works in $ \mathcal{O}(Q\cdot\log(N)\cdot\log(max(a))) $ which is around $ 4\cdot10^7 $ operations, with a low constant factor.
It is possible to optimize the solution even more by using sparse tables, to calculate $ f(l, r) $ in $ \mathcal{O}(1) $ therefore removing the $ \log(max(a)) $ factor, but we think that sparse tables are a little bit too advanced of a topic for div3 E, so we didn’t make that solution necessary.
一开始找来找去找不到bug,靠朋友发现是将 s 清零的时候用的memset搞的鬼。。。
注意:
- 不要用 memset,直接用循环清零
- 少用全局变量
- 左移右移时该括起来的括起来
- 写的时候能压行的尽量压行,代码越少错误越少
// Problem: E. Iva & Pav
// Contest: Codeforces - Codeforces Round 900 (Div. 3)
// URL: https://codeforces.com/contest/1878/problem/E
// Memory Limit: 256 MB
// Time Limit: 5000 ms
#include<iostream>
#include<algorithm>
#include<cstring> // memset
#define x first
#define y second
using namespace std;
const int N = 200010;
int n, m;
int a[N], s[N][30];
int q, l, k;
bool check(int mid) {
int value = 0;
for (int i = 0; i < 30; i ++ ) {
if ((s[mid][i]-s[l-1][i]) == (mid - l + 1)) {
value += (1 << i);
}
}
if (value >= k) return true;
else return false;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int ll, int r)
{
while (ll < r)
{
int mid = ll + r + 1 >> 1;
if (check(mid)) ll = mid;
else r = mid - 1;
}
return ll;
}
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
int t;
cin >> t ;
while (t -- ) {
cin >> n;
// O(nlog(max(a)))
for (int i = 1; i <= n ;i ++ ) {
cin >> a[i];
for(int j=0; j<30; j++)
s[i][idx] = s[i - 1][idx] + ((a[i] >> j) & 1);
}
// O(qlog(n)log(max(a)))
cin >> q;
while (q -- ) {
cin >> l >> k;
if(a[l]<k){
cout << -1 << ' ';
continue;
}
cout << bsearch_2(l, n) << ' ' ;
}
cout << '\n';
for(int i=1;i<=n;i++)
for(int j=0;j<30;j++)
s[i][j]=0;
}
return 0;
}