P4735 最大异或和
生活随笔
收集整理的這篇文章主要介紹了
P4735 最大异或和
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
P4735 最大異或和
題意:
一個非負序列a,初始長度為n,有兩種操作:
題解:
我們來看這個查詢操作,p∈[l,r],我們設整個區間的異或值為tot,
a[p]⊕a[p+1]⊕.....a[N]a[p] ⊕ a[p+1] ⊕ .....a[N]a[p]⊕a[p+1]⊕.....a[N]=tot⊕(a[1]⊕a[2].....⊕a[p?1])tot ⊕ (a[1] ⊕ a[2].....⊕a[p-1])tot⊕(a[1]⊕a[2].....⊕a[p?1])
相當于我們巧妙的將后綴問題轉換成前綴問題,那就是找一個前綴s[y]⊕(x⊕tot)的值最大,y屬于[l-1,r-1]。轉化成可持久化01Trie經典模型:
給定(l,r,x),在序列[l,r]區間中選一個數a[i],使得a[i]⊕x最大
然后按照可持久化的套路,我們將所有前綴異或和s[i]建立可持久化01Trie,算出(x⊕tot)的值后在rt[l-2]到rt[r-1]這兩顆樹上走一邊,尋找最大值
代碼:
#include<bits/stdc++.h> #define debug(a,b) printf("%s = %d\n",a,b); using namespace std; typedef long long ll; typedef pair<int, int> PII; //Fe~Jozky const ll INF_ll=1e18; const int INF_int=0x3f3f3f3f; inline ll read(){ll s=0,w=1ll;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w; } void rd_txt(){#ifdef ONLINE_JUDGE#elsefreopen("in.txt","r",stdin);#endif } const int maxn=6e5+9; struct tree{int cnt;int ch[2]; }tr[maxn*30]; int rtnum=0; int a[maxn]; int rt[maxn]; int tot=0; void insert(int now,int pre,int x){for(int i=30;i>=0;i--){int c=((x>>i)&1);tr[now].ch[c^1]=tr[pre].ch[c^1];tr[now].ch[c]=++rtnum;now=tr[now].ch[c];pre=tr[pre].ch[c];tr[now].cnt=tr[pre].cnt+1;} } int get(int L,int R,int x){int sum=0;for(int i=30;i>=0;i--){int c=((x>>i)&1);if(tr[tr[R].ch[c^1]].cnt>tr[tr[L].ch[c^1]].cnt){sum+=(1<<i);L=tr[L].ch[c^1];R=tr[R].ch[c^1]; }else {L=tr[L].ch[c];R=tr[R].ch[c]; }}return sum; }int main() {rd_txt();int n,m;cin>>n>>m;rt[0]=++rtnum;insert(rt[0],0,0);tot=0;for(int i=1;i<=n;i++){cin>>a[i];tot^=a[i];rt[i]=++rtnum;insert(rt[i],rt[i-1],tot);}for(int i=1;i<=m;i++){string op;cin>>op;int x;if(op=="A"){cin>>x;tot^=x;rt[++n]=++rtnum;insert(rt[n],rt[n-1],tot);}else if(op=="Q"){int l,r,x;cin>>l>>r>>x;l--;r--;if(l==0)printf("%d\n",get(0,rt[r],tot^x));else printf("%d\n",get(rt[l-1],rt[r],tot^x));}}return 0; }總結
以上是生活随笔為你收集整理的P4735 最大异或和的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 可持久化3--可持久化01Trie
- 下一篇: P4592 [TJOI2018]异或