Luo Gu [3822] [NOI2017] integer (tree line pressure level) .md

topic:

Luo Valley 3822

analysis:

Press questions intended to simulate finished.

Each time the up / down split into not more than \ (32 \) a separate one of the plus / minus.

(Known as "current position" under) plus consider giving a bit \ (1 \) , if this one has always been \ (0 \) , then directly into \ (1 \) . Otherwise, it should take into account the position: left (from right to left after default is low to high, the same as the writing order) to find the first \ (0 \) bits \ (the p-\) , turning it into \ (1 \ ) , and from the \ (P \) all bits of the current intermediate \ (1 \) becomes \ (0 \) .

Subtraction is similar. The first operation is to step down the left to find a \ (1 \) , which becomes \ (0 \) , and all the intermediate \ (0 \) becomes \ (1 \) .

- finding a more \ (1 \) or \ (0 \) and interval can be completed with modified segment tree, each node only need to maintain whether the interval corresponding to the full \ (0 \) or all \ (1 \) i.e. can.

It will be split into a query \ (32 \) time constant is too large, \ (3.2 \ 10. 7 Times \ ^) times and then put on modified segment tree \ (\ log 3 \ times 10 ^ 7 \) simply make life difficult. Consider pressure level, segment tree each leaf represents a plurality of continuous (use my code is \ (60 \) th) bits, looking for the first \ (1 \) / \ (0 \) instead of looking a non \ (0 \) (all \ (0 \) ) / nonconjugated (2 ^ {60} \) \ (full \ (1 \) ) number. Thus, only each modification split up into two positions of the plus / minus. Complexity \ (O (n \ log m ) \) where \ (m \) is the maximum number of bits.

Code:

Note that half of the tree line to find the first non-full \ (0 \) / non-full \ (1 \) practice numbers.

#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();
}

Guess you like

Origin www.cnblogs.com/zyt1253679098/p/10993308.html