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; }
重要的是自信,一旦有了自信,人就会赢得一切。