HDU6579 Operation

题目大意:

给定(5e5)的数列,和(5e5)个操作。操作有下面两种:

  • 数列后面加入一个数x
  • 给定区间[l,r],求出区间内随意挑出某些数的异或最大值

前缀线性基,只不过他要求在线。


代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
int t,n,m;
int d[maxn<<1][32],pos[maxn<<1][32];
int cnt;
void insert(int x)
{
    cnt++;
    for(int i=31;i>=0;--i)
    {
        d[cnt][i]=d[cnt-1][i];
        pos[cnt][i]=pos[cnt-1][i];
    }
    int cur=cnt;
    for(int i=31;i>=0;--i)
    {
        if(x&(1ll<<i))
        {
            if(d[cnt][i])
            {
                if(pos[cnt][i]<cur)
                {
                    swap(pos[cnt][i],cur);
                    swap(d[cnt][i],x);
                }
                x^=d[cnt][i];
            }
            else
            {
                d[cnt][i]=x;
                pos[cnt][i]=cur;
                break;
            }
        }
    }
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        cnt=0;
        memset(d,0,sizeof(d));
        memset(pos,0,sizeof pos);
        for(int x,i=1;i<=n;++i)
        {
            scanf("%d",&x);
            insert(x);
        }
        int lastans=0;
        for(int op,l,r,i=1;i<=m;++i)
        {
            scanf("%d",&op);
            if(op==0)
            {
                scanf("%d%d",&l,&r);
                l=(l^lastans)%cnt+1;
                r=(r^lastans)%cnt+1;
                if(l>r)swap(l,r);
                lastans=0;
                for(int i=31;i>=0;--i)
                    if(pos[r][i]>=l)lastans=max(lastans,lastans^d[r][i]);
                printf("%d
",lastans);
            }
            else
            {
                scanf("%d",&l);
                insert(l^lastans);
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/gryzy/p/15112522.html