2019 Multi-University Training Contest 1 - 1002 Operation

2019 杭電多校1 - 1002 Operation
題目鏈接:hdu 6579

題解:
貪心地維護序列的前綴線性基 (上三角形態),對於每個線性基,將出現位置靠右的數字儘可能地放在高位,也就是說在插入新數字的時候,要同時記錄對應位置上數字的出現位置,並且在找到可以插入的位置的時候,如果新數字比位置上原來的數字更靠右,就將該位置上原來的數字向低位推。
在求最大值的時候,從高位向低位遍歷,如果該位上的數字出現在詢問中區間左端點的右側且可以使答案變大,就異或到答案裏。
對於線性基的每一位,與它異或過的線性基更高位置上的數字肯定都出現在它右側 (否則它就會被插入在那個位置了),因此做法的正確性顯然。

代碼:

#include <bits/stdc++.h>
#define LL long long
#define LD long double
#define ULL unsigned long long
#define UI unsigned int
#define PII pair<int,int>
#define MPII(x,y) pair<int,int>{x,y}
#define _for(i,j,k) for(int i=j;i<=k;i++)
#define for_(i,j,k) for(int i=j;i>=k;i--)
#define efor(i,u) for(int i=head[u];i;i=net[i])
#define lowbit(x) (x&-x)
#define ls(x) x<<1
#define rs(x) x<<1|1
#define inf 0x3fffffff
//#pragma comment(linker, "/STACK:10240000000,10240000000")
using namespace std;
const int maxn = 1e6 + 5;
const int M = 1e9 + 7;
inline int mad(int a,int b){return (a+=b)>=M?a-M:a;}
struct LB{
    int a[31],b[31];
    void init(){
        for(int i=30;i>=0;i--) a[i]=0;
    }
    void insert(int x,int ind){
        for(int i=30;i>=0;i--){
            if(x&(1ll<<i)){
                if(a[i]){
                    if(ind>b[i]){
                        swap(a[i],x);
                        swap(b[i],ind);
                    }
                    x^=a[i];
                }
                else{
                    a[i]=x;
                    b[i]=ind;
                    break;
                }
            }
        }
    }
    int maxSum(){
        int ret=0;
        for(int i=30;i>=0;i--){
            if(ret&(1ll<<i)) continue;
            ret^=a[i];
        }
        return ret;
    }
}; 
LB lb[maxn];
int n,m,ta[maxn],t;
int query(int l,int r){
    int ret=0;
    for(int i=30;i>=0;i--){
        if(lb[r].b[i]>=l&&(ret^lb[r].a[i])>ret){
            ret^=lb[r].a[i];
        }
    }
    return ret;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--){
        cnt=0;
        cin>>n>>m;
        _for(i,1,n){
            cin>>ta[i];
        }
        _for(i,1,n){
            lb[i]=lb[i-1];
            lb[i].insert(ta[i],i);
        }
        int op,l,r,lastans=0;
        _for(i,1,m){
            cin>>op;
            if(op){
                cin>>ta[++n];
                ta[n]^=lastans;
                lb[n]=lb[n-1];
                lb[n].insert(ta[n],n);
            }
            else{
                cin>>l>>r;
                l = (l^lastans)%n + 1;
                r = (r^lastans)%n + 1;
                if(l>r) swap(l,r);
                lastans=query(l,r);
                cout<<lastans<<"\n";
            }
        }
        
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章