Codeforces Round #532 (Div. 2):F. Ivan and Burgers(贪心+异或基)

F. Ivan and Burgers

题目链接:https://codeforces.com/contest/1100/problem/F

题意:

给出n个数,然后有多个询问,每次回答询问所给出的区间的异或和最大值。

题解:

考虑离线做法,先把所有的询问区间按照右端点进行排序,然后从1开始逐个将ai插入,插入线性基的同时记录一下位置,最后扫一下,看看哪些的位置是不小于li的即可加入答案。

这种做法在时间复杂度上面是可行的,但是需要注意的是,如果在i这个位置插入最高位为x的线性基,同时在j这个位置又有一个最高位为x的线性基,那么对于最高位为x的线性基,我们是肯定保留后面的位置是更优的。在替换位置过后,注意一下插入的线性基也发生了变化。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5+5;
int n,q;
int c[N],ans[N],pos[N];
int a[25];
struct P{
    int l,r,id;
    bool operator < (const P &A)const{
        return r<A.r;
    }
}p[N];
void insert(int val,int id){
    for(int i=20;i>=0;i--){
        if(!((1<<i)&val)) continue ;
        if(!a[i]){
            a[i]=val;
            pos[i]=id;
            break ;
        }
        if(pos[i]<id) swap(pos[i],id),swap(a[i],val);
        val^=a[i];
    }
}
int query(int l){
    int res=0;
    for(int i=20;i>=0;i--){
        if(((res^a[i])>res) && pos[i]>=l) res^=a[i];
    }
    return res;
}
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>c[i];
    cin>>q;
    for(int i=1;i<=q;i++) cin>>p[i].l>>p[i].r,p[i].id=i;
    sort(p+1,p+q+1);
    int r=1;
    for(int i=1;i<=q;i++){
        while(r<=p[i].r) insert(c[r],r),r++;
        ans[p[i].id]=query(p[i].l);
    }
    for(int i=1;i<=q;i++) cout<<ans[i]<<'\n';
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/heyuhhh/p/10422188.html