QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#749919 | #9727. Barkley III | infCraft | WA | 0ms | 3752kb | C++17 | 5.5kb | 2024-11-15 11:24:42 | 2024-11-15 11:24:43 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define pb push_back
#define Yes cout << "Yes\n"
#define No cout << "No\n"
#define YES cout << "YES\n"
#define NO cout << "NO\n"
#define ff first
#define ss second
#define fori(x,y) for(int i=x;i<=(int)(y);++i)
#define forj(x,y) for(int j=x;j<=(int)(y);++j)
#define fork(x,y) for(int k=x;k<=(int)(y);++k)
#define debug(x) cerr << #x << " = " << x << endl
typedef unsigned long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll MOD = 998244353;
ll qpow(ll a,ll p) {ll res=1; while(p) {if (p&1) {res=res*a%MOD;} a=a*a%MOD; p>>=1;} return res;}
struct SegTree {
int n;
vector<ll> tree, tag, zero;
SegTree(int n): n(n) { // 开4倍空间
n *= 4;
tree = tag = zero = vector<ll>(n+1, 0);
}
inline int ls(int p) { return p<<1; } // 线段树左孩子
inline int rs(int p) { return p<<1|1; } // 线段树右孩子
void push_up(int p) {
tree[p] = tree[ls(p)]&tree[rs(p)];
zero[p] = (zero[ls(p)]^zero[rs(p)])&(tree[ls(p)]^tree[rs(p)]);
// zero[p] &= max(zero[ls(p)], zero[rs(p)]);
}
void build(int p, int pl, int pr, ll* arr) {
tag[p] = ULLONG_MAX;
if (pl == pr) {
tree[p] = arr[pl];
zero[p] = ~arr[pl];
return;
}
int mid = (pl+pr)>>1;
build(ls(p), pl, mid, arr);
build(rs(p), mid+1, pr, arr);
push_up(p);
}
void addtag(int p, int pl, int pr, ll d) { // 更新线段树的值并打上标记
if (pl == pr) {
tree[p] &= d;
zero[p] = ~tree[p];
return;
}
tag[p] &= d;
tree[p] &= d;
zero[p] &= d;
}
void push_down(int p, int pl, int pr) { // 向下传递tag
if (tag[p] != ULLONG_MAX) { // 如果有tag
int mid = (pl+pr)>>1;
addtag(ls(p), pl, mid, tag[p]); // 给下层节点打上标记
addtag(rs(p), mid+1, pr, tag[p]);
tag[p] = ULLONG_MAX; // 该层标记置为0
}
}
void update1(int L, int R, int p, int pl, int pr, ll d) { // 更新线段树
if (L<=pl&&R>=pr) { // [L,R]完全覆盖区间[pl, pr],完成更新
addtag(p, pl, pr, d); // 打标记
return;
}
push_down(p, pl, pr); // 没有完全覆盖,向下传递tag
int mid = (pl+pr)>>1;
if (L<=mid) update1(L, R, ls(p), pl, mid, d); // 递归更新左子树
if (R>mid) update1(L, R, rs(p), mid+1, pr, d); // 递归更新右子树
push_up(p); // 后序遍历向上更新线段树
}
void update2(int x, int p, int pl, int pr, ll d) { // 更新线段树
if (x<=pl&&x>=pr) { // [L,R]完全覆盖区间[pl, pr],完成更新
// addtag(p, d); // 打标记
tree[p] = d;
zero[p] = ~d;
tag[p] = ULLONG_MAX;
return;
}
push_down(p, pl, pr); // 没有完全覆盖,向下传递tag
int mid = (pl+pr)>>1;
if (x<=mid) update2(x, ls(p), pl, mid, d); // 递归更新左子树
else if (x>mid) update2(x, rs(p), mid+1, pr, d); // 递归更新右子树
push_up(p); // 后序遍历向上更新线段树
}
ll query(int L, int R, int p, int pl, int pr) {
if (L<=pl&&R>=pr) return tree[p]; // [L,R]完全覆盖区间[pl, pr],直接返回
push_down(p, pl, pr); // 不能覆盖区间,向下传递tag
ll res = ULLONG_MAX;
int mid = (pl+pr)>>1;
if (L<=mid) res &= query(L, R, ls(p), pl, mid); // 递归求下面的子树
if (R>mid) res &= query(L, R, rs(p), mid+1, pr); // 递归求下面的子树
return res;
}
int find(int L, int R, int p, int pl, int pr, ll a) {
if (pl == pr) return pl;
push_down(p, pl, pr);
int mid = (pl+pr)>>1;
if (L<=mid&&R<=mid) return find(L, R, ls(p), pl, mid, a);
else if (L>mid&&R>mid) return find(L, R, rs(p), mid+1, pr, a);
else {
if ((zero[ls(p)]&a&zero[p]) >= (zero[rs(p)]&a&zero[p])) return find(L, R, ls(p), pl, mid, a&zero[p]);
else return find(L, R, rs(p), mid+1, pr, a&zero[p]);
}
return 0;
}
// 外部调用
void update1(int L, int R, ll d) {
update1(L, R, 1, 1, n, d);
}
void update2(int x, ll d) {
update2(x, 1, 1, n, d);
}
ll query(int L, int R) {
if (L>R) return ULLONG_MAX;
return query(L, R, 1, 1, n);
}
int find(int L, int R) {
return find(L, R, 1, 1, n, ULLONG_MAX);
}
};
const int N = 1e6+7;
ll arr[N];
signed main() {
IOS;
int n, q;
cin >> n >> q;
fori(1, n) cin >> arr[i];
SegTree seg(n);
seg.build(1, 1, n, arr);
while (q--) {
int op; cin >> op;
if (op == 1) {
ll l, r, x;
cin >> l >> r >> x;
seg.update1(l, r, x);
}
else if (op == 2) {
ll x, d;
cin >> x >> d;
seg.update2(x, d);
}
else {
int l, r;
cin >> l >> r;
int p = seg.find(l, r);
// debug(p);
ll res = seg.query(l, p-1)&seg.query(p+1, r);
cout << res << endl;
}
// fori(1, n) cout << seg.query(i, i) << " ";
// cout << endl;
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3752kb
input:
5 9 7 7 7 6 7 3 1 5 2 1 3 3 1 5 3 1 3 1 1 2 3 3 1 3 2 2 8 3 1 3 3 1 2
output:
7 6 7 3 3 8
result:
ok 6 lines
Test #2:
score: -100
Wrong Answer
time: 0ms
memory: 3752kb
input:
10 10 6760061359215711796 1568091718842717482 1568091718842717482 1568091718842717482 5232472783634052627 8795942500783873690 1568091718842717482 1568091718842717482 1568091718842717482 1568091718842717482 1 3 5 7587422031989082829 3 6 10 1 7 8 5197616143400216932 2 4 2518604563805514908 2 2 4533959...
output:
1568091718842717482 35184372088832 176025477579040 986444436075452520
result:
wrong answer 2nd lines differ - expected: '35184908959744', found: '35184372088832'