ACM linear group study notes

https://www.cnblogs.com/31415926535x/p/11260897.html

Outline

When the last few games there have been more than school-based linear title several times before attempting ,, will think the biggest problem a different section of Xi'an or regional tournament and, at that time because of the nature of XOR know This question is certainly to use segment tree maintenance of most value range, but do not know what to deal with XOR and maximum ,, even though we later learned that the linear base can be used to process and read some blog also because it feels too difficult to bookmark collections and have not seen ,, , so these days, spent almost five days time, probably read the content of this part, I feel this is just a tool to deal specifically with a XOR problem, the light of this tool means nothing ,, many of the problems now groups are linear sets of various things ,, common example segment tree (mostly inquiry), the chain split tree (i.e. XOR tree path problems, primarily seeking to maintain LCA), FIG simple Hang electrically and the image field as a first problem that the greedy board sub-like linear change magic ,, impossible except simple linear sub-substrate to seek what most value, K value, and the cross-like properties, the following A simple record of the learning process of the past few days I learned a linear group.

Mathematical knowledge

Based on linear, although it looks very deep ,, but after three words such as overview, you will find that this is just a simple mathematical tool, it is learned the basics of linear algebra (Though long forgotten)

Linear Algebra aside, my personal understanding is that the linear base is used to represent a given set of a minimum number of a given set of linear based this collection, it can be expressed spanned a collection for large we encounter most of the title, is to use a minimum number of set \ (LB \) by exclusive-oR in the form of an array may be represented (set) \ (a \) .

We can use the \ (n-\) a \ (2 ^ i \) so that different binary array \ (a_i \) is used to represent all of the exclusive-OR \ ([0 ... 2 ^ n -1] \) of any one of number, for example: \ ([01], [10] \) can be represented by a \ (0, 1, 2, 3 \) . But if you remove the \ (a_i \) in some number, apparently set number can be represented in turn reduces some ,, think, for any set of numbers, we can find such a subset of a set of numbers \ (a_i \ ) , \ (a_i \) in any number of XOR and this number may represent the number of each set, so we have the equivalent of the original episodes were compressed, represented by a small set up,, and apparently he the maximum size is the number of bits in the binary representation,

The reason for this can be represented is because for a linear base, he can be seen as a vector group, among these vectors are linearly independent, that is not any of a vector can be represented by another vector, which is the base of linear each number is not obtained by exclusive or such other number ,, a linear combination of vectors may span a linear space ,,, (particularly a more detailed knowledge of mathematics can be seen here) or contribute

Linear action group

Most of the action in the ACM group is a linear or exclusive maintenance period the number of various properties, e.g. most value, K value, a number \ (X \) can be exclusive or of these numbers and said group linear delivery and so on. This is just a tool, mainly, and other knowledge combined.

Substantially linear board group

I do not know is that this knowledge is not so important or how ,, unlike other algorithms, linear based on good information found on the Internet very little board ,, ,, especially ,, no comment novice (I) Beginning simply do not understand ,, only hard eating in front of the mathematical derivation, and then converted into a code in his own ,,, last draw came up with a copy of your board on the basis of someone else ,,,(Not afraid of a few days to forget what is written)

Represents a linear group

By definition, a linear set is a set of numbers, and the length in general give the title ,, LL is 64, int is 32 ,, so he is like an array on the line ,,,

static const int maxbase = 35;
ll a[maxbase + 1];

Linear insertion group

The basic operation of the linear traverse a number of groups is set, and then pick one of the linear group, this process is a number \ (T \) is inserted into the current linear group ,, a linear group \ (A \) , If it is the element and \ (T \) linearly independent, then the \ (T \) is a substrate ,, he inserted into the linear group according to the definition ,, ,, ,, if found then shows a linear correlation now linear group \ (a \) may represent the number of meal after operation ,, ,, \ (T \) necessarily becomes 0 ,, (in this number can be determined whether a group represented ,,, linear

The insertion process is essentially a maintenance base linear matrix ,, there are two forms of maintenance ,, One is the impact regardless of the insertion of elements on other elements ,, maintenance of the linear matrix based on a triangular ,, this time to read complex lower; the other is to use a Gaussian elimination ,, can be inserted for elements, first with the following line to eliminate themselves, and their elimination by the above lines ,, this ensures that after inserting a matrix element linear group only the one who inserted the line that corresponds to 1 ,, other ,, are zero is a diagonal matrix.

bool insert(ll t)
{
    //暴力插入一个数,维护的是一个上三角型的线性基矩阵,时间复杂度低,当待插入元素能插入时,返回true
    for(int i = maxbase; i >= 0; --i)
    {
        if(t & (1ll << i))
        {
            if(!a[i])
            {
                a[i] = t;
                break;
            }
            t ^= a[i];
        }
    }
    if(t == 0)flag = true;
    return t;
}
bool query(ll t)
{
    // 询问t是否可以被当前线性基表示,不插入
    if(t > queryMax())return false;
    if(t == 0)return true;
    for(int i = maxbase; i >= 0; --i)
    {
        if(t & (1ll << i))
        {
            if(!a[i])
            {
                return false;
            }
            t ^= a[i];
        }
    }
    return true;
}
void Insert(ll t)
{
    //插入一个线性基,利用高斯消元法维护一个对角矩阵
    for(int i = maxbase; i >= 0; --i)
    {
        if(t >> i & 1)
        {
            if(a[i])t ^= a[i];
            else
            {
                a[i] = t;
                for(int j = i - 1; j >= 0; --j)if(a[j] && (a[i] >> j & 1))a[i] ^= a[j];
                for(int j = i + 1; j <= maxbase; ++j)if(a[j] >> j & 1)a[j] ^= a[i];
                break;
            }
        }
    }
}

Most linear group value

  • Group observed linear, apparent to the collection represented by the set of linear elements represented by the line he must lowest number is the minimum set of exclusive-OR ,, represented from low to high so long as the first non-zero return can be a substrate ,, (note that 0 is determined);
  • For maximum value, as long as we traverse the entire linear group, if the current element \ (a_i \) XOR the answer becomes large, exclusive or this one,
//询问最值
ll queryMax()
{
    ll ret = 0;
    for(int i = maxbase; i >= 0; --i)
        if((ret ^ a[i]) > ret)
            ret ^= a[i];
    return ret;
}
ll queryMin()
{
    for(int i = 0; i <= maxbase; ++i)
        if(a[i])
            return a[i];
    return 0;
}

And a plurality of linear groups, cross

and:

And say, direct force applied to a linear group, and, anyway, the line will become 0 can not be inserted in the insertion process, do not control

cross:

Pay more than cattle off the fourth school was encountered ,,(Linear base throughout the school is more than just encountered) , (Post board found only one able to understand) ,,, general idea is this post (Guessing ing)

  • The first group is referred to a linear \ (L_1 \) , the other is \ (L_2 \) , is an initial \ (L_1 \) linear group \ (All \) , a linear marker group \ (Full \) (should ..)
  • Then each time the \ (\ L_2) in a take-yl \ (V \) , if it can in \ (All \) represented, that is many times the value of the exclusive OR ,, 0 then according numerals insert the \ (v \) , he said he is a intersection. .

board:

LinearBasis merge(const LinearBasis &l1, const LinearBasis &l2)
{
    // 得到两个线性基的并
    LinearBasis ret = l1;
    for(int i = maxbase; i >= 0; --i)
        if(l2.a[i])
            ret.insert(l2.a[i]);
    return ret;
}
LinearBasis intersection(const LinearBasis &l1, const LinearBasis &l2)
{
    //得到两个线性基的交
    LinearBasis all, ret, full;
    ret.clear();
    for(int i = maxbase; i >= 0; --i)
    {
        all.a[i] = l1.a[i];
        full.a[i] = 1ll << i;
    }
    for(int i = maxbase; i >= 0; --i)
    {
        if(l2.a[i])
        {
            ll v = l2.a[i], k = 0;
            bool flag = true;
            for(int j = maxbase; j >= 0; --j)
            {
                if(v & (1ll << j))
                {
                    if(all.a[j])
                    {
                        v ^= all.a[j];
                        k ^= full.a[j];
                    }
                    else
                    {
                        // l2's basis is not in l1's;
                        flag = false;
                        all.a[j] = v;
                        full.a[j] = k;
                        break;
                    }
                }
            }
            if(flag)
            {
                ll v = 0; // get intersection by k;
                for(int j = maxbase; j >= 0; --j)
                {
                    if(k & (1ll << j))
                    {
                        v ^= l1.a[j];
                    }
                }
                ret.insert(v);  //save ans
            }
        }
    }
    return ret;
}

Seeking large group of K linear

(Do not leave pit ,,, questions ...

Complete linear base board

struct LinearBasis
{
    static const int maxbase = 35;
    bool flag = false;
    ll a[maxbase + 1];
    LinearBasis()
    {
        // memset(a, 0, sizeof a);
    }
    LinearBasis(ll *x, int n)
    {
        LinearBasis();
        build(x, n); 
    }
    void build(ll *x, int n)
    {
        for(int i = 1; i <= n; ++i)
            insert(x[i]);
    }
    void clear()
    {
        memset(a, 0, sizeof a);
    }
    bool insert(ll t)
    {
        //暴力插入一个数,维护的是一个上三角型的线性基矩阵,时间复杂度低,当待插入元素能插入时,返回true
        for(int i = maxbase; i >= 0; --i)
        {
            if(t & (1ll << i))
            {
                if(!a[i])
                {
                    a[i] = t;
                    break;
                }
                t ^= a[i];
            }
        }
        if(t == 0)flag = true;
        return t;
    }
    bool query(ll t)
    {
        // 询问t是否可以被当前线性基表示,不插入
        if(t > queryMax())return false;
        if(t == 0)return true;
        for(int i = maxbase; i >= 0; --i)
        {
            if(t & (1ll << i))
            {
                if(!a[i])
                {
                    return false;
                }
                t ^= a[i];
            }
        }
        return true;
    }
    void Insert(ll t)
    {
        //插入一个线性基,利用高斯消元法维护一个对角矩阵
        for(int i = maxbase; i >= 0; --i)
        {
            if(t >> i & 1)
            {
                if(a[i])t ^= a[i];
                else
                {
                    a[i] = t;
                    for(int j = i - 1; j >= 0; --j)if(a[j] && (a[i] >> j & 1))a[i] ^= a[j];
                    for(int j = i + 1; j <= maxbase; ++j)if(a[j] >> j & 1)a[j] ^= a[i];
                    break;
                }
            }
        }
    }
    LinearBasis merge(const LinearBasis &l1, const LinearBasis &l2)
    {
        // 得到两个线性基的并
        LinearBasis ret = l1;
        for(int i = maxbase; i >= 0; --i)
            if(l2.a[i])
                ret.insert(l2.a[i]);
        return ret;
    }
    LinearBasis intersection(const LinearBasis &l1, const LinearBasis &l2)
    {
        //得到两个线性基的交
        LinearBasis all, ret, full;
        ret.clear();
        for(int i = maxbase; i >= 0; --i)
        {
            all.a[i] = l1.a[i];
            full.a[i] = 1ll << i;
        }
        for(int i = maxbase; i >= 0; --i)
        {
            if(l2.a[i])
            {
                ll v = l2.a[i], k = 0;
                bool flag = true;
                for(int j = maxbase; j >= 0; --j)
                {
                    if(v & (1ll << j))
                    {
                        if(all.a[j])
                        {
                            v ^= all.a[j];
                            k ^= full.a[j];
                        }
                        else
                        {
                            // l2's basis is not in l1's;
                            flag = false;
                            all.a[j] = v;
                            full.a[j] = k;
                            break;
                        }
                    }
                }
                if(flag)
                {
                    ll v = 0; // get intersection by k;
                    for(int j = maxbase; j >= 0; --j)
                    {
                        if(k & (1ll << j))
                        {
                            v ^= l1.a[j];
                        }
                    }
                    ret.insert(v);  //save ans
                }
            }
        }
        return ret;
    }
    //询问最值
    ll queryMax()
    {
        ll ret = 0;
        for(int i = maxbase; i >= 0; --i)
            if((ret ^ a[i]) > ret)
                ret ^= a[i];
        return ret;
    }
    ll queryMin()
    {
        for(int i = 0; i <= maxbase; ++i)
            if(a[i])
                return a[i];
        return 0;
    }
};

Linear-based practice

Template title

Template title

Become familiar with the board ,, knock on it ,,

Greedy + linear properties of the elements inserted yl

Greedy + linear properties of the elements inserted yl

For each number set number, a second weight value, to ensure that the right to choose the number and the set number of exclusive or non-zero as long as the case where the maximum value is selected from ,, descending weight and the subscript XOR and the contribution of non-zero elements on it,

// luogu-judger-enable-o2
#include <bits/stdc++.h>
// #include <iostream>
// #include <cstdio>
// #include <cstdlib>
// #include <string.h>
// #include <vector>
// #include <algorithm>
// #include <set>
// #include <vector>
// #include <cmath>
// #include <queue>
// #include <stack>
// #include <ctime>
// #include <random>
#define aaa cout<<233<<endl;
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// mt19937 rnd(time(0));
const int inf = 0x3f3f3f3f;//1061109567 > 1e9
const ll linf = 0x3f3f3f3f3f3f3f;
const double eps = 1e-5;
const double pi = 3.14159265358979;
const int maxn = 1e4 + 5;
const int maxm = 1e4 + 5;
const int mod = 1e9 + 7;

struct LinearBasis
{
    static const int maxbase = 62;
    ll a[maxbase + 1];
    LinearBasis()
    {
        memset(a, 0, sizeof a);
    }
    LinearBasis(ll *x, int n)
    {
        LinearBasis();
        build(x, n);   
    }
    void build(ll *x, int n)
    {
        for(int i = 1; i <= n; ++i)
            insert(x[i]);
    }
    bool insert(ll t)
    {
        for(int i = maxbase; i >= 0; --i)
        {
            if(t & (1ll << i))
            {
                if(!a[i])
                {
                    a[i] = t;
                    break;
                }
                t ^= a[i];
            }
        }
        return t;
    }
    void Insert(ll t)
    {
        for(int i = maxbase; i >= 0; --i)
        {
            if(t >> i & 1)
            {
                if(a[i])t ^= a[i];
                else
                {
                    a[i] = t;
                    for(int j = i - 1; j >= 0; --j)if(a[j] && (a[i] >> j & 1))a[i] ^= a[j];
                    for(int j = i + 1; j <= maxbase; ++j)if(a[j] >> j & 1)a[j] ^= a[i];
                    break;
                }
            }
        }
    }
    LinearBasis merge(const LinearBasis &l1, const LinearBasis &l2)
    {
        LinearBasis ret = l1;
        for(int i = maxbase; i >= 0; --i)
            if(l2.a[i])
                ret.insert(l2.a[i]);
        return ret;
    }
    ll queryMax()
    {
        ll ret = 0;
        for(int i = maxbase; i >= 0; --i)
            if((ret ^ a[i]) > ret)
                ret ^= a[i];
        return ret;
    }
    ll queryMin()
    {
        for(int i = 0; i <= maxbase; ++i)
            if(a[i])
                return a[i];
        return 0;
    }
};
pair<int, ll> p[maxn];
int main()
{
    // double pp = clock();
    // freopen("233.in", "r", stdin);
    // freopen("233.out", "w", stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    int n; cin >> n;
    for(int i = 1; i <= n; ++i)cin >> p[i].second >> p[i].first;
    sort(p + 1, p + 1 + n, greater<pair<int, ll>>());
    LinearBasis l;
    int ans = 0;
    for(int i = 1; i <= n; ++i)if(l.insert(p[i].second))ans += p[i].first;
    cout << ans << endl;

    // cout << endl << (clock() - pp) / CLOCKS_PER_SEC << endl;
    return 0;
}

Number of the linear combination of group

Number of the linear combination of group

Title ask \ (01 \) Number (state) sequence may be represented by several linear group ,, is the size of the square ,,,

// luogu-judger-enable-o2
#include <bits/stdc++.h>
// #include <iostream>
// #include <cstdio>
// #include <cstdlib>
// #include <string.h>
// #include <vector>
// #include <algorithm>
// #include <set>
// #include <vector>
// #include <cmath>
// #include <queue>
// #include <stack>
// #include <ctime>
// #include <random>
#define aaa cout<<233<<endl;
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// mt19937 rnd(time(0));
const int inf = 0x3f3f3f3f;//1061109567 > 1e9
const ll linf = 0x3f3f3f3f3f3f3f;
const double eps = 1e-5;
const double pi = 3.14159265358979;
const int maxn = 1e4 + 5;
const int maxm = 1e4 + 5;
const int mod = 1e9 + 7;

struct LinearBasis
{
    static const int maxbase = 62;
    ll a[maxbase + 1];
    LinearBasis()
    {
        memset(a, 0, sizeof a);
    }
    LinearBasis(ll *x, int n)
    {
        LinearBasis();
        build(x, n);   
    }
    void build(ll *x, int n)
    {
        for(int i = 1; i <= n; ++i)
            insert(x[i]);
    }
    bool insert(ll t)
    {
        for(int i = maxbase; i >= 0; --i)
        {
            if(t & (1ll << i))
            {
                if(!a[i])
                {
                    a[i] = t;
                    break;
                }
                t ^= a[i];
            }
        }
        return t;
    }
    void Insert(ll t)
    {
        for(int i = maxbase; i >= 0; --i)
        {
            if(t >> i & 1)
            {
                if(a[i])t ^= a[i];
                else
                {
                    a[i] = t;
                    for(int j = i - 1; j >= 0; --j)if(a[j] && (a[i] >> j & 1))a[i] ^= a[j];
                    for(int j = i + 1; j <= maxbase; ++j)if(a[j] >> j & 1)a[j] ^= a[i];
                    break;
                }
            }
        }
    }
    LinearBasis merge(const LinearBasis &l1, const LinearBasis &l2)
    {
        LinearBasis ret = l1;
        for(int i = maxbase; i >= 0; --i)
            if(l2.a[i])
                ret.insert(l2.a[i]);
        return ret;
    }
    ll queryMax()
    {
        ll ret = 0;
        for(int i = maxbase; i >= 0; --i)
            if((ret ^ a[i]) > ret)
                ret ^= a[i];
        return ret;
    }
    ll queryMin()
    {
        for(int i = 0; i <= maxbase; ++i)
            if(a[i])
                return a[i];
        return 0;
    }
};
char ch[55];
int main()
{
    // double pp = clock();
    // freopen("233.in", "r", stdin);
    // freopen("233.out", "w", stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    int n, m; cin >> m >> n;
    LinearBasis l;
    int ans = 0;
    for(int i = 1; i <= n; ++i)
    {
        cin >> ch;
        ll t = 0;
        for(int j = 0; j <= m - 1; ++j)
        {
            if(ch[j] == 'O')t |= 1;
            t <<= 1;
        }
        t >>= 1;
        if(l.insert(t))++ans;
    }
    cout << (1ll << ans) % 2008 << endl;

    // cout << endl << (clock() - pp) / CLOCKS_PER_SEC << endl;
    return 0;
}

LCA tree split violence and linear chain between the path seeking group and the maximum point or exclusive rights

LCA tree split violence and linear chain between the path seeking group and the maximum point or exclusive rights

The effect of this problem is a tree, a little right, ask you for a tree path between any two points \ (u-> v \) maximum XOR and right is the number of points ,,

Path between any two points on the tree is to ask LCA ,, so by several methods that seek the LCA can be seen, and, before chain subdivision tree ,, ,, but almost forgotten to re-learn to pick up the next, ,

LCA on the problem and the same, but in a different segment tree data structure such as maintenance of, and, used to be and, most of what ,, this problem into linear base value on it, and, maintaining the linear path of the base ,, the combined linear group then it ,,,(Int data array to open several hair re fried

// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include <bits/stdc++.h>
// #include <iostream>
// #include <cstdio>
// #include <cstdlib>
// #include <string.h>
// #include <vector>
// #include <algorithm>
// #include <set>
// #include <vector>
// #include <cmath>
// #include <queue>
// #include <stack>
// #include <ctime>
// #include <random>
#define aaa cout<<233<<endl;
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// mt19937 rnd(time(0));
const int inf = 0x3f3f3f3f;//1061109567 > 1e9
const ll linf = 0x3f3f3f3f3f3f3f;
const double eps = 1e-5;
const double pi = 3.14159265358979;
const int maxn = 2e4 + 5;
const int maxm = 1e4 + 5;
const int mod = 1e9 + 7;

struct LinearBasis
{
    static const int maxbase = 63;
    ll a[maxbase + 1];
    LinearBasis()
    {
        memset(a, 0, sizeof a);
    }
    LinearBasis(ll *x, int n)
    {
        LinearBasis();
        build(x, n);   
    }
    void build(ll *x, int n)
    {
        for(int i = 1; i <= n; ++i)
            insert(x[i]);
    }
    void clear()
    {
        memset(a, 0, sizeof a);
    }
    bool insert(ll t)
    {
        for(int i = maxbase; i >= 0; --i)
        {
            if(t & (1ll << i))
            {
                if(!a[i])
                {
                    a[i] = t;
                    break;
                }
                t ^= a[i];
            }
        }
        return t;
    }
    void Insert(ll t)
    {
        for(int i = maxbase; i >= 0; --i)
        {
            if(t >> i & 1)
            {
                if(a[i])t ^= a[i];
                else
                {
                    a[i] = t;
                    for(int j = i - 1; j >= 0; --j)if(a[j] && (a[i] >> j & 1))a[i] ^= a[j];
                    for(int j = i + 1; j <= maxbase; ++j)if(a[j] >> j & 1)a[j] ^= a[i];
                    break;
                }
            }
        }
    }
    LinearBasis merge(const LinearBasis &l1, const LinearBasis &l2)
    {
        LinearBasis ret = l1;
        for(int i = maxbase; i >= 0; --i)
            if(l2.a[i])
                ret.insert(l2.a[i]);
        return ret;
    }
    void merge(const LinearBasis &r)
    {
        for(int i = maxbase; i >= 0; --i)
            if(r.a[i])
                insert(r.a[i]);
        return;
    }
    ll queryMax()
    {
        ll ret = 0;
        for(int i = maxbase; i >= 0; --i)
            if((ret ^ a[i]) > ret)
                ret ^= a[i];
        return ret;
    }
    ll queryMin()
    {
        for(int i = 0; i <= maxbase; ++i)
            if(a[i])
                return a[i];
        return 0;
    }
};
struct edge
{
    int to, nxt;
}edge[maxn * 3];
int tot, head[maxn * 3];
int top[maxn * 3];
int fa[maxn * 3];
int dep[maxn * 3];
int num[maxn * 3];
int p[maxn * 3], fp[maxn * 3];
int son[maxn * 3];
int pos;
ll a[maxn], w[maxn << 2];
void init()
{
    tot = 0;
    memset(head, -1, sizeof head);
    pos = 0;
    memset(son, -1, sizeof son);
    memset(w, 0, sizeof w);
}
void addedge(int u, int v)
{
    edge[tot].to = v;
    edge[tot].nxt = head[u];
    head[u] = tot++; 
}
void dfs1(int u, int pre, int d)
{
    dep[u] = d;
    fa[u] = pre;
    num[u] = 1;
    for(int i = head[u]; ~i; i = edge[i].nxt)
    {
        int v = edge[i].to;
        if(v != pre)
        {
            dfs1(v, u, d + 1);
            num[u] += num[v];
            if(son[u] == -1 || num[v] > num[son[u]])
                son[u] = v;
        }
    }
}
void dfs2(int u, int sp)
{
    top[u] = sp;
    p[u] = ++pos;
    fp[p[u]] = u;
    w[pos] = a[u];
    if(son[u] == -1)return;
    dfs2(son[u], sp);
    for(int i = head[u]; ~i; i = edge[i].nxt)
    {
        int v = edge[i].to;
        if(v != son[u] && v != fa[u])
            dfs2(v, v);
    }
}


struct node
{
    int l, r;
    LinearBasis lb;
}node[maxn * 6];
void pushup(int rt)
{
    node[rt].lb.merge(node[rt << 1].lb);
    node[rt].lb.merge(node[rt << 1 | 1].lb);
    // cout << endl;for(int i = 0; i <= 5; i ++)cout << node[rt << 1].lb.a[i] << "-";cout << endl << endl;
    // cout << endl;for(int i = 0; i <= 5; i ++)cout << node[rt << 1 | 1].lb.a[i] << "+";cout << endl << endl;
    // cout << endl;for(int i = 0; i <= 5; i ++)cout << node[rt].lb.a[i] << " ";cout << endl << endl;
}
void build(int rt, int l, int r)
{
    node[rt].l = l; node[rt].r = r;
    if(l == r){node[rt].lb.insert(w[l]);return;}
    int mid = l + r >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);
    pushup(rt);
    return;
}
LinearBasis ret;
void query(int rt, int l, int r)
{
    if(node[rt].l == l && node[rt].r == r)
    {
        ret.merge(node[rt].lb);
        return;
    }
    int mid = node[rt].l + node[rt].r >> 1;
    if(r <= mid)query(rt << 1, l, r);
    else if(l > mid)query(rt << 1 | 1, l, r);
    else query(rt << 1, l, mid), query(rt << 1 | 1, mid + 1, r);
}
ll getAns(int u, int v)
{
    int f1 = top[u], f2 = top[v];
    LinearBasis ans;
    while(f1 != f2)
    {
        if(dep[f1] < dep[f2])
        {
            swap(f1, f2);
            swap(u, v);
        }
        ret.clear();
        query(1, p[f1], p[u]);
        // cout << endl; cout << p[f1] << " " << p[u] << " " << f1 << " " << u << endl;for(int i = 0; i <= 5; ++i)cout << ret.a[i] << " ";cout<< endl;
        // cout <<ret.queryMax() << "----------------------" << endl;
        ans.merge(ret);
        u = fa[f1]; f1 = top[u];
    }
    ret.clear();
    if(dep[u] > dep[v])swap(u, v);
    query(1, p[u], p[v]);
    ans.merge(ret);
    return ans.queryMax();
}

int main()
{
    // double pp = clock();
    // freopen("233.in", "r", stdin);
    // freopen("233.out", "w", stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    init();
    int n, q; cin >> n >> q;
    for(int i = 1; i <= n; ++i)cin >> a[i];
    int u, v;
    for(int i = 1; i <= n - 1; ++i)
    {
        cin >> u >> v;
        addedge(u, v);
        addedge(v, u);
    }
    dfs1(1, 0, 1);
    dfs2(1, 1);
    build(1, 1, pos);
    while(q--)
    {
        cin >> u >> v;
        cout << getAns(u, v) << endl;
    }
    // for(int i = 5; i >= 0; --i)
    //     cout << node[1].lb.a[i] << endl;
    // ret.clear();
    // query(1, p[4], p[4]);
    // cout << ret.queryMax() << endl;

    // cout << endl << (clock() - pp) / CLOCKS_PER_SEC << endl;
    return 0;
}

Cattle fourth multi-passenger school xor

Cattle fourth multi-passenger school xor

This is a problem to obtain a linear range of the base and the effect that the subject ,, to give you a set number \ (a_i \) ,, then some ask \ (l, r, x \ ) ask you \ (a_l .... A_R \) in each set or whether an exclusive \ (X \) ,,,

Violence linear-based query sure T (I say is ,,,,,

Each query is a set interval or count could be exclusive \ (X \) ,, ,, turn to present a set of linear group is absent may represent \ (X \) is also the case in each of the ,,, a subset of the group that is able to cross these sets shows linear group \ (X \) ,, can represent a linear group ,, intersection simple linear group is critical to get ,,, well you can use this segment tree maintenance interval linear cross ,,, base of the inquiry, the idea is to obtain the most direct cross-ask range, then see if you can shows the number \ (the X-\) ,, but this is not necessary You may T ,,,(Do not ask me why ,,, ,, as long as the judge asked each sub-section of the cross to represent ,, whether these results are combined with the range is the answer ,,,

(Ll write once the int, crazy WA ,, there is a linear change the code group cross explosion magic ,,,,

#include <bits/stdc++.h>
// #include <iostream>
// #include <cstdio>
// #include <cstdlib>
// #include <string.h>
// #include <vector>
// #include <algorithm>
// #include <set>
// #include <vector>
// #include <cmath>
// #include <queue>
// #include <stack>
// #include <ctime>
// #include <random>
#define aaa cout<<233<<endl;
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// mt19937 rnd(time(0));
const int inf = 0x3f3f3f3f;//1061109567 > 1e9
const ll linf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-5;
const double pi = 3.14159265358979;
const int maxn = 5e4 + 5;
const int maxm = 1e4 + 5;
const int mod = 1e9 + 7;
  
  
struct LinearBasis
{
    static const int maxbase = 35;
    bool flag = false;
    ll a[maxbase + 1];
    LinearBasis()
    {
        // memset(a, 0, sizeof a);
    }
    LinearBasis(ll *x, int n)
    {
        LinearBasis();
        build(x, n); 
    }
    void build(ll *x, int n)
    {
        for(int i = 1; i <= n; ++i)
            insert(x[i]);
    }
    void clear()
    {
        memset(a, 0, sizeof a);
    }
    bool insert(ll t)
    {
        for(int i = maxbase; i >= 0; --i)
        {
            if(t & (1ll << i))
            {
                if(!a[i])
                {
                    a[i] = t;
                    break;
                }
                t ^= a[i];
            }
        }
        if(t == 0)flag = true;
        return t;
    }
    bool query(ll t)
    {
        if(t > queryMax())return false;
        if(t == 0)return true;
        for(int i = maxbase; i >= 0; --i)
        {
            if(t & (1ll << i))
            {
                if(!a[i])
                {
                    return false;
                }
                t ^= a[i];
            }
        }
        return true;
    }
    void Insert(ll t)
    {
        for(int i = maxbase; i >= 0; --i)
        {
            if(t >> i & 1)
            {
                if(a[i])t ^= a[i];
                else
                {
                    a[i] = t;
                    for(int j = i - 1; j >= 0; --j)if(a[j] && (a[i] >> j & 1))a[i] ^= a[j];
                    for(int j = i + 1; j <= maxbase; ++j)if(a[j] >> j & 1)a[j] ^= a[i];
                    break;
                }
            }
        }
    }
    LinearBasis merge(const LinearBasis &l1, const LinearBasis &l2)
    {
        LinearBasis ret = l1;
        for(int i = maxbase; i >= 0; --i)
            if(l2.a[i])
                ret.insert(l2.a[i]);
        return ret;
    }
    LinearBasis intersection(const LinearBasis &l1, const LinearBasis &l2)
    {
        LinearBasis all, ret, full;
        ret.clear();
        for(int i = maxbase; i >= 0; --i)
        {
            all.a[i] = l1.a[i];
            full.a[i] = 1ll << i;
        }
        for(int i = maxbase; i >= 0; --i)
        {
            if(l2.a[i])
            {
                ll v = l2.a[i], k = 0;
                bool flag = true;
                for(int j = maxbase; j >= 0; --j)
                {
                    if(v & (1ll << j))
                    {
                        if(all.a[j])
                        {
                            v ^= all.a[j];
                            k ^= full.a[j];
                        }
                        else
                        {
                            // l2's basis is not in l1's;
                            flag = false;
                            all.a[j] = v;
                            full.a[j] = k;
                            break;
                        }
                    }
                }
                if(flag)
                {
                    ll v = 0; // get intersection by k;
                    for(int j = maxbase; j >= 0; --j)
                    {
                        if(k & (1ll << j))
                        {
                            v ^= l1.a[j];
                        }
                    }
                    ret.insert(v);  //save ans
                }
            }
        }
        return ret;
    }
    ll queryMax()
    {
        ll ret = 0;
        for(int i = maxbase; i >= 0; --i)
            if((ret ^ a[i]) > ret)
                ret ^= a[i];
        return ret;
    }
    ll queryMin()
    {
        for(int i = 0; i <= maxbase; ++i)
            if(a[i])
                return a[i];
        return 0;
    }
}lb[maxn];
  
  
LinearBasis node[maxn << 2];
void pushup(int rt)
{
    node[rt] = node[rt].intersection(node[rt << 1], node[rt << 1 | 1]);
}
void build(int rt, int l, int r)
{
    if(l == r)
    {
        node[rt] = lb[l];
        return;
    }
    int mid = l + r >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);
    pushup(rt);
    return;
}
LinearBasis ans;
bool query(int rt, int l, int r, int L, int R, ll x)
{
    if(L <= l && r <= R)
    {
        return node[rt].query(x);
    }
    int mid = l + r >> 1;
    bool flag1, flag2;
    flag1 = flag2 = true;
    if(L <= mid)flag1 = query(rt << 1, l, mid, L, R, x);
    if(R >  mid)flag2 = query(rt << 1 | 1, mid + 1, r, L, R, x);
    return flag1 & flag2;
}
  
int main()
{
    // double pp = clock();
    // freopen("233.in", "r", stdin);
    // freopen("233.out", "w", stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
  
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; ++i)
    {
        int num; cin >> num;
        ll x;
        for(int j = 1; j <= num; ++j)
        {
            cin >> x;
            lb[i].insert(x);
        }
    }
    build(1, 1, n);
    int l, r;ll x;
    while(m--)
    {
        cin >> l >> r >> x;
        if(query(1, 1, n, l, r, x))cout << "YES" << endl;
        else cout << "NO" << endl;
    }
      
    // cout << endl << (clock() - pp) / CLOCKS_PER_SEC << endl;
    return 0;
}

Hang electrical multi-correction first Operation

Hang electrical multi-correction first Operation

This effect is the problem for a given array, there are two operations, a query is a maximum interval of the exclusive OR and the other is to add a value ,, In this latter array ,,,

This problem is also the reason I learned to induce linear group ,,

Commentary title will maintain direct data structures T ,, ,, I did not test positive solutions are greedy of maintaining a prefix linear base , at each insertion ,, if a number can be inserted into the ,, ,, high as possible (this can ensure close r can be inserted in the high number of possible ,,

In other words ,, for any of a range of arbitrary length ,, no matter how much ,,, his most linear base is 30 (for this topic) ,,, so we only need to maintain the previous r appear later Thus each new interrogation yl ,, ,, are seen later than the l-yl group can occur at r linear in order to realize this process ,, ,,, linear to each group each bit plus a flag \ (P_i \) ,, when you insert a new number ,,, as much as possible to put him high ,,, (when confronted with a possible insertion location, to insert him in here, and then push down other groups ,,,

This problem can not be reckless, directly open ll ,,, will mle ,,,

#include <bits/stdc++.h>
// #include <iostream>
// #include <cstdio>
// #include <cstdlib>
// #include <string.h>
// #include <vector>
// #include <algorithm>
// #include <set>
// #include <vector>
// #include <cmath>
// #include <queue>
// #include <stack>
// #include <ctime>
// #include <random>
#define aaa cout<<233<<endl;
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// mt19937 rnd(time(0));
const int inf = 0x3f3f3f3f;//1061109567 > 1e9
const ll linf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-5;
const double pi = 3.14159265358979;
const int maxn = 5e5 + 5;
const int maxm = 1e4 + 5;
const int mod = 1e9 + 7;
  
  
struct LinearBasis
{
    typedef int type;
    static const int maxbase = 30;
    bool flag = false;
    type a[maxbase + 1];
    type p[maxbase + 1];
    LinearBasis()
    {
        memset(a, 0, sizeof a);
        memset(p, 0, sizeof p);
    }
    LinearBasis(type *x, int n)
    {
        LinearBasis();
        build(x, n); 
    }
    void build(type *x, int n)
    {
        for(int i = 1; i <= n; ++i)
            insert(x[i]);
    }
    void clear()
    {
        memset(a, 0, sizeof a);
        memset(p, 0, sizeof p);
    }
    bool insert(type t)
    {
        //暴力插入一个数,维护的是一个上三角型的线性基矩阵,时间复杂度低,当待插入元素能插入时,返回true
        for(int i = maxbase; i >= 0; --i)
        {
            if(t & (1ll << i))
            {
                if(!a[i])
                {
                    a[i] = t;
                    break;
                }
                t ^= a[i];
            }
        }
        if(t == 0)flag = true;
        return t;
    }
    bool insert2(type t, type pos)
    {
        for(int i = maxbase; i >= 0; --i)
        {
            if(t & (1ll << i))
            {
                if(!a[i])
                {
                    a[i] = t;
                    p[i] = pos;
                    break;
                }
                else if(pos > p[i])
                {
                    swap(pos, p[i]);
                    swap(t, a[i]);
                }
                t ^= a[i];
            }
        }
        if(t == 0)flag = true;
        return t;
    }
    bool query(type t)
    {
        // 询问t是否可以被当前线性基表示,不插入
        if(t > queryMax())return false;
        if(t == 0)return true;
        for(int i = maxbase; i >= 0; --i)
        {
            if(t & (1ll << i))
            {
                if(!a[i])
                {
                    return false;
                }
                t ^= a[i];
            }
        }
        return true;
    }
    void Insert(type t)
    {
        //插入一个线性基,利用高斯消元法维护一个对角矩阵
        for(int i = maxbase; i >= 0; --i)
        {
            if(t >> i & 1)
            {
                if(a[i])t ^= a[i];
                else
                {
                    a[i] = t;
                    for(int j = i - 1; j >= 0; --j)if(a[j] && (a[i] >> j & 1))a[i] ^= a[j];
                    for(int j = i + 1; j <= maxbase; ++j)if(a[j] >> j & 1)a[j] ^= a[i];
                    break;
                }
            }
        }
    }
    LinearBasis merge(const LinearBasis &l1, const LinearBasis &l2)
    {
        // 得到两个线性基的并
        LinearBasis ret = l1;
        for(int i = maxbase; i >= 0; --i)
            if(l2.a[i])
                ret.insert(l2.a[i]);
        return ret;
    }
    LinearBasis intersection(const LinearBasis &l1, const LinearBasis &l2)
    {
        //得到两个线性基的交
        LinearBasis all, ret, full;
        ret.clear();
        for(int i = maxbase; i >= 0; --i)
        {
            all.a[i] = l1.a[i];
            full.a[i] = 1ll << i;
        }
        for(int i = maxbase; i >= 0; --i)
        {
            if(l2.a[i])
            {
                type v = l2.a[i], k = 0;
                bool flag = true;
                for(int j = maxbase; j >= 0; --j)
                {
                    if(v & (1ll << j))
                    {
                        if(all.a[j])
                        {
                            v ^= all.a[j];
                            k ^= full.a[j];
                        }
                        else
                        {
                            // l2's basis is not in l1's;
                            flag = false;
                            all.a[j] = v;
                            full.a[j] = k;
                            break;
                        }
                    }
                }
                if(flag)
                {
                    type v = 0; // get intersection by k;
                    for(int j = maxbase; j >= 0; --j)
                    {
                        if(k & (1ll << j))
                        {
                            v ^= l1.a[j];
                        }
                    }
                    ret.insert(v);  //save ans
                }
            }
        }
        return ret;
    }
    //询问最值
    type queryMax()
    {
        type ret = 0;
        for(int i = maxbase; i >= 0; --i)
            if((ret ^ a[i]) > ret)
                ret ^= a[i];
        return ret;
    }
    type queryMax(type l)
    {
        type ret = 0;
        for(int i = maxbase; i >= 0; --i)
            if((ret ^ a[i]) > ret && l <= p[i])
                ret ^= a[i];
        return ret;
    }
    type queryMin()
    {
        for(int i = 0; i <= maxbase; ++i)
            if(a[i])
                return a[i];
        return 0;
    }
}lb[maxn];
int main()
{
    // double pp = clock();
    // freopen("233.in", "r", stdin);
    // freopen("233.out", "w", stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
  
    int t; cin >> t;
    while(t--)
    {
        int n, m;
        cin >> n >> m;
        ll x;
        for(int i = 1; i <= n; ++i)
        {
            cin >> x;
            lb[i] = lb[i - 1]; 
            lb[i].insert2(x, i);
        }
        int op;
        ll lstans = 0;
        while(m--)
        {
            cin >> op;
            if(!op)
            {
                ll l, r;cin >> l >> r;
                l = (l ^ lstans) % n + 1;
                r = (r ^ lstans) % n + 1;
                if(l > r)swap(l, r);
                lstans = lb[r].queryMax(l);
                cout << lstans << endl;
            }
            else
            {
                ll x;cin >> x;
                x ^= lstans;
                lb[++n] = lb[n - 1];
                lb[n].insert2(x, n);
            }
            
        }

    }
      
    // cout << endl << (clock() - pp) / CLOCKS_PER_SEC << endl;
    return 0;
}

loading

Also has a few problems have time to fix the regional tournament that ,,,, such as Xi'an Road ,, cf the Road ,, looks like a prototype problem Hang electricity ,,,

Guess you like

Origin www.cnblogs.com/31415926535x/p/11260897.html