2022春每日一題:Day 33
阿新 • • 發佈:2022-03-11
題目:[USACO 6.1.3] Cow XOR
沒找到這題具體網址,這個題就是求最大異或區間(總長度儘量小,右端點儘量大)
嗯很顯然一個[l,r]的異或和=s[r]s[l-1],那麼現在有了優秀的n2做法
不難(很難)聯想trie樹,列舉1到n每次把1...i的異或和加入trie樹中,然後跑一遍找最大值(史記上就是trie樹維護這個n^2演算法,降低了複雜度)
程式碼:
#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> const int N=1e5+5; using namespace std; int n,m,tot,ret=-1,lr,rr,a[N],sum; namespace trietree { struct trie { int son[2],tag; }e[N*22]; void insert(int x,int id) { int p=0; for(int i=21;i>=0;i--) { int k=x>>i&1; if(!e[p].son[k]) e[p].son[k]=++tot; p=e[p].son[k]; } e[p].tag=id; } int query(int x,int &ans) { int p=0; for(int i=21;i>=0;i--) { int k=x>>i&1; if(!e[p].son[k^1]) p=e[p].son[k]; else p=e[p].son[k^1],ans+=1<<i; } return e[p].tag; } } using namespace trietree; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int x; scanf("%d",&x); sum^=x; insert(sum,i); int ans=0; int l=query(sum,ans); if(ans>ret) { ret=ans; rr=i,lr=l; } } printf("%d %d %d\n",ret,lr+1,rr); return 0; }