2019 HDU multi-school training first B-Operation

Topic links: http://acm.hdu.edu.cn/showproblem.php?pid=6579

The meaning of problems: there is a sequence of length n integers a, there are two modes of operation:
0 LR: [, R & lt L] selected from some of the figures, and that their exclusive or maximum, maximum output;
. 1 x: the x additional end of the sequence, and let n = n + 1.
Mandatory subject line, lastans answer 0 represents the last operation, the initial zero.
0 for each operation, so that l = (l xor lastans) mod n + 1, r = (r xor lastans) mod n + 1, if l> r two switching elements.
For each action 1, let x = x xor lastans.

The game when, after reading this question, see XOR and maximum, the first thought is linear base. XOR-based linear range and the maximum, the feeling is not handled well, suddenly thought of linear groups have merged this operation can not be moved to the linear base line tree it? So I try to write a (wrong solution) code is as follows:

//这是一份错解
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
int n, q, a[MAXN];
struct L_B
{
    int a[32];
    void init()
    {
        memset(a, 0, sizeof(a));
    }
    bool insert(int val)
    {
        for (int i = 30; i >= 0; --i)
        {
            if (val & (1 << i))
            {
                if (!a[i])
                {
                    a[i] = val;
                    break;
                }
                else
                    val ^= a[i];
            }
        }
        return val > 0;
    }
    int query_max()
    {
        int ret = 0;
        for (int i = 30; i >= 0; --i)
        {
            if ((ret ^ a[i]) > ret)
                ret ^= a[i];
        }
        return ret;
    }
    L_B merge(L_B m)
    {
        L_B ret;
        for (int i = 0; i < 31; i++)
            ret.a[i] = a[i];
        for (int i = 0; i < 31; i++)
        {
            for (int j = i; j >= 0; j--)
            {
                if (m.a[i] & (1 << j))
                {
                    if (ret.a[j])
                        m.a[i] ^= ret.a[j];
                    else
                    {
                        ret.a[j] = m.a[i];
                        break;
                    }
                }
            }
        }
        return ret;
    }
} tr[MAXN * 4];
void build(int l, int r, int root)
{
    if (l == r)
    {
        tr[root].init();
        tr[root].insert(a[l]);
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, root << 1);
    build(mid + 1, r, root << 1 | 1);
    tr[root] = tr[root << 1].merge(tr[root << 1 | 1]);
}
void add(int l, int r, int pos, int root, int ans)
{
    if (l == pos && r == pos)
    {
        tr[root].init();
        tr[root].insert(ans);
        return;
    }
    int mid = (l + r) >> 1;
    if (pos > mid)
        add(mid + 1, r, pos, root << 1 | 1, ans);
    else
        add(l, mid, pos, root << 1, ans);
    tr[root] = tr[root << 1].merge(tr[root << 1 | 1]);
}
L_B query(int L, int R, int l, int r, int root)
{
    if (L <= l && r <= R)
        return tr[root];
    int mid = (l + r) >> 1;
    if (L <= mid && mid < R)
        return query(L, R, l, mid, root << 1).merge(query(L, R, mid + 1, r, root << 1 | 1));
    if (L <= mid)
        return query(L, R, l, mid, root << 1);
    if (R > mid)
        return query(L, R, mid + 1, r, root << 1 | 1);
}
int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        memset(a, 0, sizeof(a));
        scanf("%d %d", &n, &q);
        for (int i = 1; i <= n; ++i)
            scanf("%d", &a[i]);
        int len = n + q;
        build(1, len, 1);
        int lastans = 0, op;
        L_B ans;
        for (int i = 1; i <= q; ++i)
        {
            scanf("%d", &op);
            if (op == 0)
            {
                int l, r;
                scanf("%d %d", &l, &r);
                l = (l ^ lastans) % n + 1;
                r = (r ^ lastans) % n + 1;
                if (l > r)
                    swap(l, r);
                ans.init();
                ans = query(l, r, 1, len, 1);
                lastans = ans.query_max();
                printf("%d\n", lastans);
            }
            else if (op == 1)
            {
                int x;
                scanf("%d", &x);
                x = x ^ lastans;
                n++;
                add(1, len, n, 1, x);
            }
        }
    }
    return 0;
}

After writing the code to confirm no problem, try to pay out of, TLE. Double-check your code, overtime can not find a place, to find ways to optimized or TLE, once again forget about the time complexity, suddenly found linear groups together the operations are O (900), and does not operate like the tree line is O (1). After the time complexity of the calculation is wrong, I began to doubt my thinking is correct. (The game I did not have the .jpg)

Solution:
the practice of violence can maintain data base interval linear structure, but certainly had not. (Cry)
greedy maintained prefix linear base sequence (a triangular shape), linear for each group, will appear on the right of the position of the digital high as possible, that is to say when the new number is inserted, to be recorded at the same time occurrence position corresponding to the position number, and can be found when the inserted location, if the new digital number further to the right than the original position, to the original position of the push toward low numbers.
When selecting the maximum value, from high to low traversal, if the number on the right of the left end of the bit interval appears in the interrogation and answer can be made larger, it is in the answer to the exclusive OR.
For every linear group, and it had exclusive or digital linear based on a higher position certainly appear in the right of it (or it will be inserted at that position), so the practice is clearly correctness.

Explanation:
In fact the problem solution is to use a greedy idea for a linear base, the numbers for each location are its contributions to the highest level, then we can sequence every position to build a linear group, linear group number in each position are taken as the right, while each of the linear sequence record the position of every group contributions. When inserting new numbers before a location on its base the previous linear linear groups are the same, and then find the location of the new digital able to contribute, the new digital insertion of only the highest contribution of one, but it may also be substituted by digital update linear behind several groups, substituted therefore proceed with the update number.
When selecting the maximum value and, as long as this bit linear yl traversed from high to low, if the number on the left end of the bit interval of the right appears in the challenge and the answer can be made larger, it is in the answer to the exclusive OR.

code show as below:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
int a[MAXN], L_B[MAXN][31], pos[MAXN][31];
void add(int p, int x)
{
    int k = p;
    for (int i = 30; i >= 0; --i)
    {
        L_B[p][i] = L_B[p - 1][i];
        pos[p][i] = pos[p - 1][i];
    }
    for (int i = 30; i >= 0; --i)
    {
        if (x >> i)
        {
            if (!L_B[p][i])
            {
                L_B[p][i] = x;
                pos[p][i] = k;
                break;
            }
            else
            {
                if (k > pos[p][i])
                {
                    swap(k, pos[p][i]);
                    swap(x, L_B[p][i]);
                }
                x ^= L_B[p][i];
            }
        }
    }
}
int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        int n, q, op, ans = 0;
        scanf("%d %d", &n, &q);
        for (int i = 1; i <= n; ++i)
        {
            scanf("%d", &a[i]);
            add(i, a[i]);
        }
        while (q--)
        {
            scanf("%d", &op);
            if (op == 1)
            {
                scanf("%d", &a[++n]);
                a[n] ^= ans;
                add(n, a[n]);
            }
            else
            {
                int l, r;
                scanf("%d %d", &l, &r);
                l = (l ^ ans) % n + 1;
                r = (r ^ ans) % n + 1;
                if (l > r)
                    swap(l, r);
                ans = 0;
                for (int j = 30; j >= 0; --j)
                    if ((ans ^ L_B[r][j]) > ans && pos[r][j] >= l)
                        ans ^= L_B[r][j];
                printf("%d\n", ans);
            }
        }
        for (int i = 1; i <= n; ++i)
        {
            for (int j = 30; j >= 0; --j)
            {
                L_B[i][j] = 0;
                pos[i][j] = 0;
            }
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/red-leaves/p/11269487.html