QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#222833 | #6631. Maximum Bitwise OR | fickle | TL | 119ms | 59704kb | C++20 | 5.9kb | 2023-10-21 19:05:39 | 2023-10-21 19:05:39 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define Mp make_pair
#define pb push_back
#define SZ(a) (int(a.size()))
typedef long long ll;
typedef double db;
typedef std::pair<int, int> pii;
typedef std::vector<int> vi;
#define log(...) fprintf(stderr, __VA_ARGS__)
std::mt19937_64 gen(std::chrono::system_clock::now().time_since_epoch().count());
ll get(ll l, ll r) { std::uniform_int_distribution<ll> dist(l, r); return dist(gen); }
const int N = 1e5 + 100;
const bool MIN = false, MAX = true;
const int Bsz = 30, inf = 2e9; // B = log(n) block size
struct rmq { // O(n)-O(1) rmq 1e9
int n, m, z[N], mn[20][N/20], pre[N], suf[N], stk[Bsz+10], bit[N];
bool type; // Min or Max rmq do Min rmq
void prework() {
int cur = inf;
for(int i = 1; i <= n; i++) {
if(i % Bsz == 0) cur = inf;
cur = min(cur, z[i]), pre[i] = cur;
}
cur = inf;
for(int i = n; i; i--) {
cur = min(cur, z[i]), suf[i] = cur;
if(i % Bsz == 0) cur = inf;
}
m = n / Bsz;
for(int i = 0; i <= m; i++) mn[0][i] = inf;
for(int i = 1; i <= n; i++) mn[0][i / Bsz] = min(mn[0][i / Bsz], z[i]);
for(int k = 1; 1 << k <= m + 1; k++)
for(int i = 0; i + (1 << k) - 1 <= m; i++)
mn[k][i] = min(mn[k - 1][i], mn[k - 1][i + (1 << k - 1)]);
int tp = 0, l = 0; cur = 0;
for(int i = 1; i <= n; i++) {
if(i % Bsz == 0) tp = cur = 0, l = i;
while(tp && z[stk[tp]] >= z[i]) cur ^= 1 << (stk[tp] - l), tp--;
bit[i] = cur ^= 1 << (i - l), stk[++tp] = i;
}
}
void init(int arr[], int n_, bool type_) {
// false for min, true for max
n = n_, type = type_;
for(int i = 1; i <= n; i++)
z[i] = (type ? -arr[i] : arr[i]);
prework();
}
int get_b(int l, int r) { // block min
if(l > r) return inf;
int x = 31 - __builtin_clz(r - l + 1); // log(r - l + 1)
return min(mn[x][l], mn[x][r - (1 << x) + 1]);
}
int get(int l, int r) { // query min
if(l / Bsz != r / Bsz) return min(get_b(l / Bsz + 1, r / Bsz - 1), min(suf[l], pre[r]));
else return z[l + __builtin_ctz(bit[r] >> (l % Bsz))];
}
int query(int l, int r) { return type ? -get(l, r) : get(l, r); }
} qr[30];
int n, q, a[N], f[N][20], mx[N][20], rmx[30][N], nxt[N][30], pre[N][30], lg2[N];
int qor(int l, int r) {
if(r < l) return 0;
int lg = lg2[r - l + 1];
return f[l][lg] | f[r - (1 << lg) + 1][lg];
}
int qmx(int l, int r) {
if(r < l) return 0;
int lg = lg2[r - l + 1];
return max(mx[l][lg], mx[r - (1 << lg) + 1][lg]);
}
void solve() {
cin >> n >> q;
for(int i = 1; i <= n; i++) {
cin >> a[i];
f[i][0] = a[i];
mx[i][0] = a[i];
for(int j = 29, lst = -1; j >= 0; j--) {
if(a[i] >> j & 1) lst = j;
rmx[j][i] = lst;
}
}
for(int i = 0; i < 30; i++) {
qr[i].init(rmx[i], n, MAX);
}
for(int j = 1; 1 << j < n; j++)
for(int i = 1; i + (1 << j) - 1 <= n; i++)
f[i][j] = f[i][j - 1] | f[i + (1 << (j - 1))][j - 1],
mx[i][j] = max(mx[i][j - 1], mx[i + (1 << (j - 1))][j - 1]);
for(int i = 0; i < 30; i++) {
nxt[n + 1][i] = n + 1;
}
for(int i = n; i; i--) {
for(int j = 0; j < 30; j++)
if(a[i] >> j & 1) nxt[i][j] = i;
else nxt[i][j] = nxt[i + 1][j];
}
for(int i = 0; i < 30; i++) {
pre[0][i] = 0;
}
for(int i = 1; i <= n; i++) {
for(int j = 0; j < 30; j++)
if(a[i] >> j & 1) pre[i][j] = i;
else pre[i][j] = pre[i - 1][j];
}
while(q--) {
int l, r;
cin >> l >> r;
int mxa = qmx(l, r), sumor = qor(l, r);
int mxor = (1 << (32 - __builtin_clz(mxa))) - 1;
auto getLR = [&](int x) {
return Mp(__builtin_ctz(x), 31 - __builtin_clz(x));
};
auto [L, R] = getLR(sumor ^ mxor);
if(sumor == mxor) {
cout << mxor << " 0\n";
} else {
vi pos = {l - 1, r + 1};
for(int nw = l, sum = 0; ; ) {
int to = n + 1;
for(int i = 0; i < 30; i++)
if((sum >> i & 1) == 0) to = min(to, nxt[nw][i]);
if(to <= r) {
pos.pb(to);
nw = to;
sum ^= a[nw];
} else break;
}
for(int nw = r, sum = 0; ; ) {
int to = 0;
for(int i = 0; i < 30; i++)
if((sum >> i & 1) == 0) to = max(to, pre[nw][i]);
if(to >= l) {
pos.pb(to);
nw = to;
sum ^= a[nw];
} else break;
}
sort(pos.begin(), pos.end());
pos.erase(unique(pos.begin(), pos.end()), pos.end());
int fl = 0;
for(int i = 1; i < SZ(pos); i++) {
int ll = pos[i - 1] + 1, rr = pos[i] - 1;
if(rr < ll) continue;
if(qr[L].query(ll, rr) >= R) fl = 1;
}
for(int i = 1; i + 1 < SZ(pos); i++) {
int nowsum = qor(l, pos[i] - 1) | qor(pos[i] + 1, r);
auto [nowL, nowR] = getLR(mxor ^ nowsum);
if(rmx[nowL][pos[i]] >= nowR) fl = 1;
}
cout << mxor << ' ' << (fl ? 1 : 2) << '\n';
}
}
}
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
lg2[0] = -1;
for(int i = 1; i < N; i++) lg2[i] = lg2[i >> 1] + 1;
int _; cin >> _; for(int cas = 1; cas <= _; cas++) solve();
cerr << "time: " << (db)clock()/CLOCKS_PER_SEC << "s\n";
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 59704kb
input:
1 3 2 10 10 5 1 2 1 3
output:
15 2 15 0
result:
ok 4 number(s): "15 2 15 0"
Test #2:
score: 0
Accepted
time: 119ms
memory: 59672kb
input:
100000 1 1 924704060 1 1 1 1 149840457 1 1 1 1 515267304 1 1 1 1 635378394 1 1 1 1 416239424 1 1 1 1 960156404 1 1 1 1 431278082 1 1 1 1 629009153 1 1 1 1 140374311 1 1 1 1 245014761 1 1 1 1 445512399 1 1 1 1 43894730 1 1 1 1 129731646 1 1 1 1 711065534 1 1 1 1 322643984 1 1 1 1 482420443 1 1 1 1 20...
output:
1073741823 2 268435455 2 536870911 2 1073741823 2 536870911 2 1073741823 2 536870911 2 1073741823 2 268435455 2 268435455 2 536870911 2 67108863 2 134217727 2 1073741823 2 536870911 2 536870911 2 268435455 2 536870911 2 536870911 2 536870911 2 268435455 2 268435455 2 1073741823 2 16777215 2 10737418...
result:
ok 200000 numbers
Test #3:
score: -100
Time Limit Exceeded
input:
50000 2 2 924896435 917026400 1 2 1 2 2 2 322948517 499114106 1 2 2 2 2 2 152908571 242548777 1 1 1 2 2 2 636974385 763173214 1 2 1 1 2 2 164965132 862298613 1 1 1 2 2 2 315078033 401694789 1 2 1 2 2 2 961358343 969300127 2 2 1 2 2 2 500628228 28065329 1 2 1 2 2 2 862229381 863649944 1 2 2 2 2 2 541...