Wannafly Challenge 14 E Invalid Position (Linear Basis + Union Lookup)

Link: https://www.nowcoder.com/acm/contest/81/E
Source: Niuke.com

Topic description

Given a 1-base array {a}, there are N operations, each of which invalidates a position. The weight of an interval is defined as the maximum value of the XOR sum of selected numbers in this interval. Find the maximum value of the weights of all intervals that do not contain invalid positions before each operation.

Enter description:

 
  

The first line reads a positive integer (1 <= n <= 10 5 )

The second line reads n positive integers, the i-th represents a[i] (0<= a[i] <= 10 9 )

The third line reads n positive integers, the i-th represents the position of x[i], which is the i-th operation, ensuring that x[i] are different from each other.

Problem-solving idea: The linear basis maintains the XOR maximum sum, and then uses the union search to maintain the interval connectivity. We consider all the queries from the back to the front, which is equivalent to continuously inserting numbers, and then continuously combining the intervals (linear basis) That's it.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

struct XXJ
{
    ll d[61];
    bool insert(ll val)
    {
        for (int i = 60; i >= 0; i--)
            if (val & (1LL << i))
            {
                if (!d[i])
                {
                    d[i] = val;
                    break;
                }
                val ^= d[i];
            }
        return val > 0;
    }
    ll query_max()
    {
        ll ret = 0;
        for (int i = 60; i >= 0; i--)
            if ((ret ^ d [i])> ret)
                ret ^ = d [i];
        return ret;
    }
    ll query_min()
    {
        for (int i = 0; i <= 60; i++)
            if (d[i])
                return d[i];
        return 0;
    }
};

void merge(XXJ &x, XXJ &y, XXJ &z)
{
    XXJ tmp;
    for (int i = 60; i >= 0; i--)
        tmp.d[i] = y.d[i];
    for (int i = 60; i >= 0; i--)
        if (z.d[i])
        {
            ll tp = z.d[i];
            for (int i = 60; i >= 0; i--)
                if (tp & (1LL << i))
                    if (!tmp.d[i])
                    {
                        tmp.d[i] = tp;
                        break;
                    }
                    else
                        tp ^= tmp.d[i];
        }
    for (int i = 60; i >= 0; i--)
        x.d[i] = tmp.d[i];
}

int a[100005];
int q[100005];
XXJ s[100005];
int force[100005];
int pre[100005];

int find(int x)
{
    return pre[x] == x ? x : pre[x] = find(pre[x]);
}

intmain()
{

    for (int i = 0; i <= 100000; i++)
        pre[i] = i;

    int N;
    scanf("%d", &N);
    for (int i = 0; i < N; i++)
    {
        scanf("%d", &a[i]);
        s[i + 1].insert(a[i]);
    }

    for (int i = 0; i < N; i++)
    {
        scanf("%d", &q[i]);
    }

    ll ans = -1000;

    for (int i = N - 1; i >= 0; i--)
    {

        if (vis[q[i] - 1] == 1)//Whether it is connected to the left, if so, merge it
        {
            int fx = find(q[i] - 1);
            int fy = find(q[i]);
            pre[fy] = fx;
            force[q[i]] = 1;
            merge(s[fx], s[fy], s[fx]);
        }

        if (vis[q[i] + 1] == 1)//right
        {
            int fx = find(q[i] + 1);
            int fy = find(q[i]);
            pre[fy] = fx;
            force[q[i]] = 1;
            merge(s[fx], s[fy], s[fx]);
        }

        int fx = find(q[i]);
        force[q[i]] = 1;
        ans = max(ans, s[fx].query_max());//ans records the last maximum value at the same time, so that you can query other intervals by the way
        q[i] = ans;
    }

    for (int i = 0; i < N; i++)
        printf("%d\n", q[i]);

    return 0;
}




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325989818&siteId=291194637