首页 > 技术文章 > 2017 ICPC西安区域赛 A - XOR ,线段树合并线性基

lhclqslove 2018-10-08 16:04 原文

题目链接:A - XOR

题意;给个数组,每次询问一个区间你可以挑任意个数的数字异或和 然后在或上k的最大值

题解:线性基不知道的先看这个,一个线性基可以log的求最大值把对应去区间的线性基求出来然后用线段树维护线性基

就可以了。还要用快读。

#include<bits/stdc++.h>
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e4+5;
int n,q,a[N];
unsigned int k;
namespace IO {
    const int MX = 4e7; //1e7 占用内存 11000kb
    char buf[MX]; int c, sz;
    void begin() {
        c = 0;
        sz = fread(buf, 1, MX, stdin);//一次性全部读入
        /*int tot = 1;
        char now;
        while((now = getchar()) != EOF){
            buf[tot++] = now;
        }
        sz = tot;*/
    }
    inline bool read(int &t) {
        while (c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;
        if (c >= sz) return false;//若读完整个缓冲块则退出
        bool flag = 0; if(buf[c] == '-') flag = 1, c++;
        for(t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++) t = t * 10 + buf[c] - '0';
        if(flag) t = -t;
        return true;
    }
}
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[N<<2];
void build(int l,int r,int rt)
{
    if(l==r)
    {
         tr[rt].init();
        tr[rt].insert(a[l]);
        return ;
    }
    int m=l+r>>1;
    build(ls);
    build(rs);
    tr[rt]=tr[rt<<1].merge(tr[rt<<1|1]);
}
L_B query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return tr[rt];
    }
    int m=l+r>>1;
    if(L<=m&&m<R)return query(L,R,ls).merge(query(L,R,rs));
    if(L<=m)return query(L,R,ls);
    if(R>m)return query(L,R,rs);
}
int main() {
    IO::begin();
   int T;
   IO::read(T);
    while(T--)
    {
        int kk;
        IO::read(n);IO::read(q);IO::read(kk);
        k=kk;
        k=~k;
        for(int i=1;i<=n;i++)
        {
            IO::read(a[i]);
            a[i]&=k;
        }
        k=~k;
        build(1,n,1);
        while(q--)
        {
            int l,r;
            IO::read(l);IO::read(r);
            L_B ans=query(l,r,1,n,1);
            int an=ans.query_max();
            an|=k;
            printf("%d\n",an);
        }
    }
}

 

一个线性基可以log的求最大值把对应去区间的线性基求出来然后#include<bits/stdc++.h>

推荐阅读