Codeforces 1878E- Iva & Pav (div3-区间操作)

题目链接:https://codeforces.com/contest/1878/problem/E
题目大意: t 组数据 ,每组给出一个 n 长的 a 序列 ,q 个询问 ,询问 f(l,r) ≥ k 的 最大索引 r ,其中 f(l,r) 表示 a 序列从 l 到 r 的按位与&值。
题目思路: 区间操作,容易想到线段树、树状数组、分块,此题可以用静态的分块操作。题目很裸,在暴力写法基础上二分+分块就能通过此题

#pragma GCC optimize(2)
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#define endl '\n'
#define fr first
#define sc second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<ll, ll> pii;
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
const ll INF_ = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
ll n, m, k, x, y, l, r, res = 0, sum = 0, ma = 0, ma_r = 0, mi = INF;
ll a[N], st[N], ed[N], belong[N], ans[N], block;
void f(ll l)
{
    ll L = l, R = n, mid;
    sum = a[l];
    for (int i = l + 1; i <= ed[belong[l]]; i++)
        sum &= a[i];
    while (L <= R) {
        mid = (L + R) >> 1;
        res = sum;
        if (belong[mid] == belong[l]) {
            res = a[l];
            for (int j = l; j <= mid; j++)
                res &= a[j];
        } else {
            for (int j = belong[l] + 1; j < belong[mid]; j++)
                res &= ans[j];
            for (int j = st[belong[mid]]; j <= mid; j++)
                res &= a[j];
        }
        if (res >= k) {
            ma_r = mid;
            L = mid + 1;
        } else
            R = mid - 1;
    }
}
void solve()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    ll q;
    cin >> q;
    block = (ll)sqrt(n);
    for (int i = 1; i <= block; i++) {
        st[i] = n / block * (i - 1) + 1;
        ed[i] = n / block * i;
    }
    ed[block] = n;
    for (int i = 1; i <= block; i++) {
        res = a[st[i]];
        belong[st[i]] = i;
        for (int j = st[i] + 1; j <= ed[i]; j++) {
            belong[j] = i;
            res &= a[j];
        }
        ans[i] = res;
    }
    while (q--) {
        ma_r = -1;
        cin >> l >> k;
        f(l);
        cout << ma_r << " ";
    }
    cout << endl;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    // cout.tie(0);
    ll _;
    cin >> _;
    while (_--)
        solve();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值