тема:
Анализ:
Пресс вопросы предназначены для имитации законченным.
Каждый раз , когда вверх / вниз , разделилась на не более чем \ (32 \) отдельный один из плюс / минус.
(Известный как "текущей позиции" под плюс) рассмотреть вопрос о предоставлении немного \ (1 \) , если один всегда был \ (0 \) , а затем непосредственно в \ (1 \) . В противном случае, он должен принимать во внимание позицию: слева (справа налево после прерванного низкого до высокого, так же , как и порядок написания) , чтобы найти первый \ (0 \) бит \ (Р- \) , превращая его в \ (1 \ ) , и из \ (Р \) все биты тока промежуточного \ (1 \) становится \ (\ 0) .
Вычитание аналогично. Первая операция на шаг вниз влево , чтобы найти \ (\ 1) , который становится \ (\ 0) , а все промежуточное \ (0 \) становится \ (\ 1) .
- нахождение более \ (1 \) или \ (0 \) и интервал может быть завершено с модифицированным дерева сегмента, каждый узел нужно только поддерживать ли соответствующее интервал до полного \ (0 \) или всех \ (1 \) , т.е. может.
Он будет разделен на запроса \ (32 \) постоянная времени слишком велико, \ (3,2 \ 10 7 раз \ ^) раз , а затем положить на модифицированный сегмент дерева \ (\ LOG 3 \ раз 10 ^ 7 \) просто сделать жизнь трудной. Рассмотрим уровень давления, сегмент дерева каждый лист представляет собой множество непрерывных (использовать мой код \ (60 \) й) битов, ищет первый \ (1 \) / \ (0 \) вместо того , чтобы искать A Non \ (0 \) (все \ (0 \) ) / несопр (2 ^ {60} \) \ (полный \ (1 \) ) число. Таким образом, только каждая модификация разделить на две позиции плюс / минус. Сложность \ (О (п \ лог - т ) \) , где \ (т \) максимальное число битов.
Код:
Обратите внимание , что половина дерева линии , чтобы найти первый не полный \ (0 \) / неполноэкранных \ (1 \) числа практики.
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
using namespace std;
namespace zyt
{
template<typename T>
inline bool read(T &x)
{
char c;
bool f = false;
x = 0;
do
c = getchar();
while (c != EOF && c != '-' && !isdigit(c));
if (c == EOF)
return false;
if (c == '-')
f = true, c = getchar();
do
x = x * 10 + c - '0', c = getchar();
while (isdigit(c));
if (f)
x = -x;
return true;
}
template<typename T>
inline void write(T x)
{
static char buf[20];
char *pos = buf;
if (x < 0)
putchar('-'), x = -x;
do
*pos++ = x % 10 + '0';
while (x /= 10);
while (pos > buf)
putchar(*--pos);
}
typedef unsigned long long ull;
const int N = 1e6 + 10, DIGIT = 60;
const ull BASE = 1ULL << DIGIT;
namespace Segment_Tree
{
struct node
{
ull val;
bool all0, all1, tag0, tag1;
}tree[N << 2];
void cov0(const int rot)
{
tree[rot].val = 0;
tree[rot].all0 = tree[rot].tag0 = true;
tree[rot].all1 = tree[rot].tag1 = false;
}
void cov1(const int rot)
{
tree[rot].val = BASE - 1ULL;
tree[rot].all1 = tree[rot].tag1 = true;
tree[rot].all0 = tree[rot].tag0 = false;
}
void update(const int rot)
{
tree[rot].all0 = (tree[rot << 1].all0 && tree[rot << 1 | 1].all0);
tree[rot].all1 = (tree[rot << 1].all1 && tree[rot << 1 | 1].all1);
}
void pushdown(const int rot)
{
if (tree[rot].tag0)
{
cov0(rot << 1), cov0(rot << 1 | 1);
tree[rot].tag0 = false;
}
else if (tree[rot].tag1)
{
cov1(rot << 1), cov1(rot << 1 | 1);
tree[rot].tag1 = false;
}
}
void cover0(const int rot, const int lt, const int rt, const int ls, const int rs)
{
if (ls <= lt && rt <= rs)
{
cov0(rot);
return;
}
int mid = (lt + rt) >> 1;
pushdown(rot);
if (ls <= mid)
cover0(rot << 1, lt, mid, ls, rs);
if (rs > mid)
cover0(rot << 1 | 1, mid + 1, rt, ls, rs);
update(rot);
}
void cover1(const int rot, const int lt, const int rt, const int ls, const int rs)
{
if (ls <= lt && rt <= rs)
{
cov1(rot);
return;
}
int mid = (lt + rt) >> 1;
pushdown(rot);
if (ls <= mid)
cover1(rot << 1, lt, mid, ls, rs);
if (rs > mid)
cover1(rot << 1 | 1, mid + 1, rt, ls, rs);
update(rot);
}
void change(const int rot, const int lt, const int rt, const int pos, const ull x)
{
if (pos > rt)
return;
if (lt == rt)
{
tree[rot].val = x;
tree[rot].all0 = (x == 0);
tree[rot].all1 = (x == (BASE - 1ULL));
return;
}
int mid = (lt + rt) >> 1;
pushdown(rot);
if (pos <= mid)
change(rot << 1, lt, mid, pos, x);
else
change(rot << 1 | 1, mid + 1, rt, pos, x);
update(rot);
}
ull query(const int rot, const int lt, const int rt, const int pos)
{
if (lt == rt)
return tree[rot].val;
int mid = (lt + rt) >> 1;
pushdown(rot);
if (pos <= mid)
return query(rot << 1, lt, mid, pos);
else
return query(rot << 1 | 1, mid + 1, rt, pos);
}
int find0(const int rot, const int lt, const int rt, const int pos)
{
if (lt == rt)
return lt;
int mid = (lt + rt) >> 1;
pushdown(rot);
if (pos <= mid && !tree[rot << 1].all1)
{
int ans = find0(rot << 1, lt, mid, pos);
if (ans <= N)
return ans;
}
if (!tree[rot << 1 | 1].all1)
return find0(rot << 1 | 1, mid + 1, rt, pos);
else
return N + 1;
}
int find1(const int rot, const int lt, const int rt, const int pos)
{
if (lt == rt)
return lt;
int mid = (lt + rt) >> 1;
pushdown(rot);
if (pos <= mid && !tree[rot << 1].all0)
{
int ans = find1(rot << 1, lt, mid, pos);
if (ans <= N)
return ans;
}
if (!tree[rot << 1 | 1].all0)
return find1(rot << 1 | 1, mid + 1, rt, pos);
else
return N + 1;
}
void init()
{
cov0(1);
}
}
ull extract(const ull a, const int l, const int r)
{
return (a & ((1ULL << r) - 1ULL)) >> l;
}
bool check(const ull a, const int p)
{
return a & (1ULL << p);
}
void add(const ull a, const int p)
{
using namespace Segment_Tree;
ull now = query(1, 0, N, p);
if (now + a >= BASE)
{
int pos = find0(1, 0, N, p + 1);
ull tmp = query(1, 0, N, pos);
change(1, 0, N, pos, tmp + 1ULL);
if (pos > p + 1)
cover0(1, 0, N, p + 1, pos - 1);
}
change(1, 0, N, p, (now + a) % BASE);
}
void sub(const ull a, const int p)
{
using namespace Segment_Tree;
ull now = query(1, 0, N, p);
if (now < a)
{
int pos = find1(1, 0, N, p + 1);
ull tmp = query(1, 0, N, pos);
change(1, 0, N, pos, tmp - 1ULL);
if (pos > p + 1)
cover1(1, 0, N, p + 1, pos - 1);
}
change(1, 0, N, p, (now - a + BASE) % BASE);
}
int work()
{
using namespace Segment_Tree;
int n, t1, t2, t3;
read(n), read(t1), read(t2), read(t3);
init();
while (n--)
{
int opt;
read(opt);
if (opt == 1)
{
int a, b;
read(a), read(b);
if (a > 0) //ADD
{
add(extract(a, 0, DIGIT - b % DIGIT) << (b % DIGIT), b / DIGIT);
add(extract(a, DIGIT - b % DIGIT, DIGIT), b / DIGIT + 1);
}
else if (a < 0)
{
a = -a;
sub(extract(a, 0, DIGIT - b % DIGIT) << (b % DIGIT), b / DIGIT);
sub(extract(a, DIGIT - b % DIGIT, DIGIT), b / DIGIT + 1);
}
}
else
{
int k;
read(k);
write(check(query(1, 0, N, k / DIGIT), k % DIGIT) ? 1 : 0), putchar('\n');
}
}
return 0;
}
}
int main()
{
#ifdef BlueSpirit
freopen("3822.in", "r", stdin);
freopen("3822.out", "w", stdout);
#endif
return zyt::work();
}