Codeforces Round 900 (Div. 3)
1.Atcoder Beginner Contest 3122.Educational Codeforces Round 152 (Rated for Div. 2)3.Codeforces Round 889 (Div. 2)4.Codeforces Round 888 (Div. 3)5.Codeforces Round 847 (Div. 3)6.Codeforces Round 890 (Div. 2)7.Codeforces Round 892 (Div. 2)8.Codeforces Round 893 (Div. 2)9.Educational Codeforces Round 15310.Codeforces Round 891 (Div. 3)11.Codeforces Round 894 (Div. 3)12.Educational Codeforces Round 154 (Rated for Div. 2)13.Codeforces Round 896 (Div. 2)14.Codeforces Round 855 (Div. 3)15.codeforces round 895 (div. 3)
16.Codeforces Round 900 (Div. 3)
17.Codeforces Round 901 (Div. 2)18.Codeforces Round 903 (Div. 3)E
题意:
给你一个数组a, 定义f(l, r) = a[l] & a[l + 1]...&a[r],现在给你q次询问,每次给你一个l,k,求一个最大的r使得f(l, r) >= k
思路:
先拆位计算,就把原数组看成一个二进制的二维数组n行30列,这样的话可以发现对于一个区间[l, r]来说,只有当某一列在这段区间内全为一才能有贡献
所以要先求一下每一列的前缀和,这样就可以O(1)判断某一段是不是全一,那样每次查询我们就二分找到最后一个符合条件的(如果x符合,那么小于x的肯定也符合因为都是一)
inline void solve()
{
int n; cin >> n;
std::vector<int> a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
vector<array<int, 30>> s(n + 1);
for (int i = 1; i <= n; i++)
for (int j = 0; j < 30; j++)
{
s[i][j] = s[i - 1][j];
if (a[i] >> j & 1) s[i][j]++;
}
int q; cin >> q;
while (q--)
{
int t, k; cin >> t >> k;
int l = t, r = n;
auto check = [&](int l, int r)
{
LL ans = 0;
for (int i = 0; i < 30; i++)
if (s[r][i] - s[l - 1][i] == r - l + 1) ans += 1 << i;
return ans >= k;
};
while (l < r)
{
int mid = (l + r + 1) / 2;
if (check(t, mid)) l = mid;
else r = mid - 1;
}
if (check(t, l)) cout << l << ' ';
else cout << -1 << ' ';
}
cout << endl;
}
本文作者:自动机
本文链接:https://www.cnblogs.com/monituihuo/articles/17735373.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步