BZOJ4260 - Codechef REBXOR(trie)
阿新 • • 發佈:2020-08-13
題意
給定一個N個元素的陣列,求任意兩個不重疊的連續區間的異或和之和的最大值。
思路
先預處理出異或字首和,然後用trie樹維護預處理出每個位置到左端點的最大的區間異或和。反方向也處理一遍。最後列舉中間的分割位置即可。
#include <bits/stdc++.h> #define endl '\n' #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0) #define FILE freopen(".//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout) #define FI freopen(".//data_generator//in.txt","r",stdin) #define FO freopen("res.txt","w",stdout) #define pb push_back #define mp make_pair #define seteps(N) fixed << setprecision(N) typedef long long ll; using namespace std; /*-----------------------------------------------------------------*/ ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} #define INF 0x3f3f3f3f const int N = 5e5 + 10; const int MX = 1e7 + 10; const double eps = 1e-5; int tr[MX][2]; int ct; void insert(int x) { int cur = 0; for(int i = 30; i >= 0; i--) { bool ntp = (x & (1 << i)); if(!tr[cur][ntp]) { tr[cur][ntp] = ++ct; cur = ct; tr[cur][0] = tr[cur][1] = 0; } else { cur = tr[cur][ntp]; } } } int findmax(int x) { int cur = 0; int res = 0; for(int i = 30; i >= 0; i--) { bool ntp = (x & (1 << i)); if(tr[cur][!ntp]) { cur = tr[cur][!ntp]; res ^= (1 << i); } else { cur = tr[cur][ntp]; } } return res; } int arr[N]; int pre[N]; int last[N]; int mxp[N]; int mxl[N]; int main() { IOS; int n; cin >> n; for(int i = 1; i <= n; i++) { cin >> arr[i]; } n++; for(int i = 1; i <= n; i++) { pre[i] = (pre[i - 1] ^ arr[i]); } for(int i = n; i >= 1; i--) { last[i] = (last[i + 1] ^ arr[i]); } for(int i = 0; i <= n; i++) { insert(pre[i]); mxp[i] = max(mxp[i - 1], findmax(pre[i])); } ct = 0; tr[0][0] = tr[0][1] = 0; for(int i = n; i >= 0; i--) { insert(last[i]); mxl[i] = max(mxl[i - 1], findmax(last[i])); } int ans = 0; for(int i = 1; i <= n - 1; i++) { ans = max(ans, mxp[i] + mxl[i + 1]); } cout << ans<< endl; }