题意:给定N个数,Q次询问,求区间最大异或和。

思路:一开始想的线性基+线段树。单次线性基合并的复杂度为20*20,结合线段树,复杂度为O(NlogN*20*20);显然,超时。

超时代码:

#include<bits/stdc++.h>
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep2(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=2000010;
int a[maxn]; vector<int>G[maxn];
void read(int &x){
    x=0; char c=getchar();
    while(c>'9'||c<'0') c=getchar();
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
}
void add(vector<int>&Now,vector<int>&p)
{
    rep(i,0,20){
        int x=p[i]; if(!x) continue;
        rep2(j,20,0){
            if(x&(1<<j)){
                if(Now[j]) x^=Now[j];
                else { Now[j]=x;break;}
           }
        }
    }
}
void build(int Now,int L,int R)
{
    rep(i,0,20) G[Now].pb(0);
    if(L==R){
        int x=a[L]; if(!x) return;
        rep2(j,20,0){
            if(x&(1<<j)){
                if(G[Now][j]) x^=G[Now][j];
                else { G[Now][j]=x;break;}
           }
        }
       return ;
    }
    int Mid=(L+R)>>1;
    build(Now<<1,L,Mid); build(Now<<1|1,Mid+1,R);
    G[Now]=G[Now<<1]; add(G[Now],G[Now<<1|1]);
}
void query(int Now,int L,int R,int l,int r,vector<int>& res)
{
    if(l<=L&&r>=R) { res=G[Now]; return ;}
    int Mid=(L+R)>>1;
    rep(i,0,20) res.pb(0);
    if(l<=Mid){
         vector<int>t;
         query(Now<<1,L,Mid,l,r,t);
         res=t;
    }
    if(r>Mid) {
         vector<int>t;
         query(Now<<1|1,Mid+1,R,l,r,t);
         add(res,t);
    }
}
int main()
{
    int N,M,L,R; scanf("%d",&N);
    rep(i,1,N) read(a[i]);
    build(1,1,N);
    scanf("%d",&M);
    while(M--){
        read(L); read(R);
        vector<int>t;
        query(1,1,N,L,R,t);
        int res=0; rep2(i,20,0) if((res^t[i])>res) res^=t[i];
        printf("%d\n",res);
    }
    return 0;
}
View Code

相关文章:

  • 2021-11-24
  • 2022-12-23
  • 2022-01-07
  • 2022-01-07
  • 2021-07-17
  • 2021-07-07
  • 2022-12-23
  • 2021-06-16
猜你喜欢
  • 2022-01-11
  • 2021-08-13
  • 2021-09-29
  • 2021-09-12
  • 2022-01-11
  • 2021-11-02
  • 2021-11-28
相关资源
相似解决方案