日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ2741 【FOTILE模拟赛】L 【可持久化trie + 分块】

發布時間:2024/7/19 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ2741 【FOTILE模拟赛】L 【可持久化trie + 分块】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目

FOTILE得到了一個長為N的序列A,為了拯救地球,他希望知道某些區間內的最大的連續XOR和。
即對于一個詢問,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r。
為了體現在線操作,對于一個詢問(x,y):
l = min ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).
r = max ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).
其中lastans是上次詢問的答案,一開始為0。

輸入格式

第一行兩個整數N和M。
第二行有N個正整數,其中第i個數為Ai,有多余空格。
后M行每行兩個數x,y表示一對詢問。

輸出格式

共M行,第i行一個正整數表示第i個詢問的結果。

輸入樣例

3 3

1 4 3

0 1

0 1

4 3

輸出樣例

5

7

7

提示

HINT

N=12000,M=6000,x,y,Ai在signed longint范圍內。

題解

區間異或和最大,轉化為兩個前綴和

多次詢問不同區間,用可持久化trie樹

但每次要任意選出兩個數,而常規的trie樹只支持一個數詢問區間和它的最大異或值,不能處理區間內任意兩個數異或和最大值
何破?

我們不可能每次詢問\(O(n^2logn)\)枚舉其中一個數
那就預處理!
如果我們能預處理出每個區間異或最大值,就是\(O(n^2logn)\)預處理,\(O(1)\)查詢

能不能均攤一下?
分塊!
我們只預處理每個塊頭到其后面所有位置的數異或的最大值
具體的,設\(f[i][j]\)表示\(i\)塊開頭位置到\(j\)中所有數異或的最大值,記塊頭為\(u\),則\(f[i][j]\)即為區間\([u,j]\)的答案
算出\(f[i][j]\)只需要枚舉每個\(j\)就可以了
具體地,\(f[i][j] = max(f[i][j - 1],query(j,區間[u,j - 1]))\)

那么每次詢問的時候,對于\(l\)之后的第一個塊頭\(u\),可以得到出后面的答案\(f[u][r]\)
所以我們只需要計算區間\([l,u - 1]\)的數與其后面的數的最大異或值
這個區間大小不會超過\(\sqrt{n}\),所以可以直接統計

總的復雜度\(O(n\sqrt{n}logn)\)
【坑點,給出的x,y可能超過int范圍】

#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #define LL long long int using namespace std; const int maxn = 12005,Bit = 31,maxm = 6000000,INF = 100000000; inline LL read(){LL out = 0,flag = 1; char c = getchar();while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}return out * flag; } LL n,m,A[maxn],sum[maxn],bin[40]; LL f[200][maxn],block[maxn],B,lans; struct trie{int ch[maxm][2],sum[maxm],rt[maxn],cnt;int ins(int pre,int x){int tmp,u;tmp = u = ++cnt;for (int i = Bit; i >= 0; i--){ch[u][0] = ch[pre][0];ch[u][1] = ch[pre][1];sum[u] = sum[pre] + 1;LL t = x & bin[i]; t >>= i;pre = ch[pre][t];u = ch[u][t] = ++cnt;}sum[u] = sum[pre] + 1;return tmp;}LL query(int u,int v,int x,int dep){if (dep < 0) return 0;LL t = x & bin[dep]; t >>= dep;if (sum[ch[u][t ^ 1]] - sum[ch[v][t ^ 1]])return bin[dep] + query(ch[u][t ^ 1],ch[v][t ^ 1],x,dep - 1);return query(ch[u][t],ch[v][t],x,dep - 1);} }T; int main(){bin[0] = 1; for (int i = 1; i <= Bit; i++) bin[i] = bin[i - 1] << 1;n = read(); m = read(); B = (int)sqrt(n) + 1;n++;for (int i = 2; i <= n; i++) A[i] = read();for (int i = 1; i <= n; i++){sum[i] = sum[i - 1] ^ A[i];T.rt[i] = T.ins(T.rt[i - 1],sum[i]);block[i] = i / B;}for (int i = 1; i <= n; i++){if (i == 1 || block[i] != block[i - 1]){int b = block[i];for (int j = i; j <= n; j++){f[b][j] = max(f[b][j - 1],T.query(T.rt[j - 1],T.rt[i - 1],sum[j],Bit));}}}n--;LL l,r,x,y;while (m--){x = read(); y = read();l = min (((x + lans) % n) + 1, ((y + lans) % n) + 1);r = max (((x + lans) % n) + 1, ((y + lans) % n) + 1) + 1;lans = 0;if (block[l] != block[r]) lans = f[block[l] + 1][r];for (int i = l; block[i] == block[l] && i < r; i++){lans = max(lans,T.query(T.rt[r],T.rt[i],sum[i],Bit));}printf("%lld\n",lans);}return 0; }

轉載于:https://www.cnblogs.com/Mychael/p/8711218.html

總結

以上是生活随笔為你收集整理的BZOJ2741 【FOTILE模拟赛】L 【可持久化trie + 分块】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。