CF 1100F Ivan and Burgers

Here

仅作笔记和理解

题意

给你 n n n个数, q q q个询问,每次询问某个区间选取一些数进行异或操作能够得到的最大值。
1 ≤ n ≤ 500000 1\leq n \leq 500000 1n500000
1 ≤ q ≤ 500000 1\leq q \leq 500000 1q500000

训练的时候看到这题没多久就想到了线性基,之前知道线性基的大概用法,只是一直没有写过,于是现场学了一下。

手模了几个数插入的过程,感觉自己懂了一点吧
先来一个插入的模板

/************************/
ll p[65];
void ins(int val)
{
    for(int i=63;i>=0;i--)
    {
        if(val&(1<<i))
        {
            if(!p[i])
            {
                p[i]=val;
                break;
            }
            val^=p[i];
        }
    }
}
ll getmax()
{
    ll ans=0;
    for(int i=63;i>=0;i--)
    {
        if((ans^p[i])>ans)
        {
            ans^=p[i];
        }
    }
    return ans;
}
/************************/

CF 1100F Ivan and Burgers_第1张图片
插入过程差不多这样吧
然后就会发现每个数都可以用p数组里面的某几个数异或得到,那么询问最大值的时候我们只要贪心地选取就可以了,询问最小值的话很明显就是p数组里面的最小值了。

对于本题,由于上面的线性基只能维护一整个区间的最大值,不能维护某个子区间的最大值,所以考虑维护每一个二进制位的数出现的最右侧位置。

Template Code

///线性基
///O(nlogn)
///注意是int还是longlong
/************************/
const int MAXN=5e5+100,MAXB=32;
#define datatype int
//#define datatype long long
int las[MAXN][MAXB],curpos[MAXB];
datatype curp[MAXB],base[MAXN][MAXB];
datatype a[MAXN];
void init()
{
    for(int i=0;i<=MAXB-1;++i)
    {
        curp[i]=0;
        curpos[i]=0;
    }
}
void ins(datatype val,int pos)
{
    for(int i=MAXB-1;i>=0;--i)
    {
        if(val&(1ll<<i))
        {
            if(curpos[i]<pos)
            {
                swap(curp[i],val);
                swap(curpos[i],pos);
            }
            if(curp[i])
            {
                val^=curp[i];
            }
            else
            {
                curp[i]=val;
                curpos[i]=pos;
                break;
            }
        }
    }
}
void getdata(int n)
{
    for(int i=1;i<=n;++i)
    {
        cin>>a[i];
        ins(a[i],i);
        for(int j=MAXB-1;j>=0;--j)
        {
            base[i][j]=curp[j];
            las[i][j]=curpos[j];
        }
    }
}
ll getmax(int l,int r)
{
    ll ans=0;
    for(int i=MAXB-1;i>=0;i--)
    {
        if(las[r][i]>=l&&(base[r][i]^ans)>ans)
        {
            ans^=base[r][i];
        }
    }
    return ans;
}
#undef datatype
/************************/

Full AC Code

/****************************
* Author : 水娃             *
* Date : 2020-08-10-19.25.29*
****************************/
#pragma GCC optimize(3,"Ofast","inline")
#include
using namespace std;
#define mst(a,b) memset(a,b,sizeof(a))
#define ll long long
#define debug(a) cout<<#a<<" is "<
#define ull unsigned long long
#define fi first
#define se second
typedef pair<int,int>pii;
typedef pair<ll,int>pli;
typedef pair<int,ll>pil;
typedef pair<ll,ll>pll;
const ull mo=(ull)1e9+7;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
///线性基
///O(nlogn)
///注意是int还是longlong
/************************/
const int MAXN=5e5+100,MAXB=32;
#define datatype int
//#define datatype long long
int las[MAXN][MAXB],curpos[MAXB];
datatype curp[MAXB],base[MAXN][MAXB];
datatype a[MAXN];
void init()
{
    for(int i=0;i<=MAXB-1;++i)
    {
        curp[i]=0;
        curpos[i]=0;
    }
}
void ins(datatype val,int pos)
{
    for(int i=MAXB-1;i>=0;--i)
    {
        if(val&(1ll<<i))
        {
            if(curpos[i]<pos)
            {
                swap(curp[i],val);
                swap(curpos[i],pos);
            }
            if(curp[i])
            {
                val^=curp[i];
            }
            else
            {
                curp[i]=val;
                curpos[i]=pos;
                break;
            }
        }
    }
}
void getdata(int n)
{
    for(int i=1;i<=n;++i)
    {
        cin>>a[i];
        ins(a[i],i);
        for(int j=MAXB-1;j>=0;--j)
        {
            base[i][j]=curp[j];
            las[i][j]=curpos[j];
        }
    }
}
ll getmax(int l,int r)
{
    ll ans=0;
    for(int i=MAXB-1;i>=0;i--)
    {
        if(las[r][i]>=l&&(base[r][i]^ans)>ans)
        {
            ans^=base[r][i];
        }
    }
    return ans;
}
#undef datatype
/************************/
void work()
{
    int n;
    cin>>n;
    getdata(n);
    int q,l,r;
    cin>>q;
    while(q--)
    {
        cin>>l>>r;
        cout<<getmax(l,r)<<"\n";
    }
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    ///int T;cin>>T;while(T--)
        work();
    return 0;
}

你可能感兴趣的:(数学)