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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

字典树andXOR*

發布時間:2025/7/14 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 字典树andXOR* 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

A.HDU 4825

你需要寫一種數據結構:

  • 往其中加入一個正整數;
  • 找出一個正整數,使得該數與詢問數的異或結果最大。

\(n\le 10^5\)

將數按二進制從高位到低位插入字典樹。
查詢時從高位往低位貪心。

Code

#include<cstdio> using namespace std; const int maxn=100003,maxlog=33; int t[maxn*maxlog][2],cnt; void insert(long long x){int p=1;for(int i=32;i>=0;i--){int nxt=(x>>i)&1;if(!t[p][nxt])t[p][nxt]=++cnt;p=t[p][nxt];} } long long query(long long x){int p=1;long long ret=0;for(int i=32;i>=0;i--){int nxt=!((x>>i)&1);if(t[p][nxt])p=t[p][nxt],ret|=(long long)nxt<<i;else p=t[p][!nxt],ret|=(long long)(!nxt)<<i;}return ret; } int n,m; int main(){int T;scanf("%d",&T);for(int TT=1;TT<=T;TT++){scanf("%d%d",&n,&m);cnt=1;for(int i=0;i<=n*maxlog;i++)t[i][0]=t[i][1]=0;for(int i=1;i<=n;i++){long long x;scanf("%lld",&x);insert(x);}printf("Case #%d:\n",TT);while(m--){long long x;scanf("%lld",&x);printf("%lld\n",query(x));}}return 0; }

B. HDU 5536

有一個序列 \(s\) ,求 \(\max_{i,j,k,i≠j≠k} (s_i+s_j) \oplus s_k\)
\(1≤T≤1000\)
\(3≤n≤1000\)
\(0≤si≤10^9\)
There are at most \(10\) testcases with \(n>100\)
\(\text{Time Limit=9s}\)

直接 \(O(n^2\log n)\) 暴力插字典樹。

C. BZOJ 4260

有一個序列 \(A\) ,求 \(\max ((A[l_1] \oplus A[l_1+1] \oplus \dots \oplus A[r_1])+(A[l_2] \oplus A[l_2+1] \oplus \dots \oplus A[r_2]))(1\le l_1\le r_1<l_2\le r_2\le n)\)
\(n\le 4*10^5\)

處理出:
\(pre[i]=a[1] \oplus a[2] \oplus \dots \oplus a[i]\)
\(suf[i]=a[i] \oplus a[i+1] \oplus \dots \oplus a[n]\)
\(B[i]=\max(\max_{j\le i}pre[i] \oplus pre[j-1],B[i-1])\)
\(C[i]=\max(\max_{j≥i}suf[i] \oplus suf[j+1],C[i+1])\)
答案 \(=\max_{i\in [1,n-1]}(B[i]+C[i+1])\)

D. POJ 3764

有一棵樹,有邊權,求異或和最大的路徑的異或和。

\(dp[i]\) 為從1到 \(i\) 的路徑的異或和,答案 \(=\max_{i,j}(dp[i] \oplus dp[j])\)
請自己證明。

E. HDU 4757

一棵樹, \(Q\) 次詢問節點 \(x\) 到節點 \(y\) 的路徑上點權與 \(x\) 的異或的最大值。

可持久化trie

F. HDU 5661

\(\max_{a\le x\le b,c\le y\le d}(x \oplus y)(a,b,c,d\le 10^{18})\)

從高位往低位貪心。

Code

#include<cstdio> using namespace std; const int maxlog=60; bool valid(long long ans,int i,long long bit,long long l,long long r){bit=ans|(bit<<i);return (bit|((1ll<<i)-1))>=l&&bit<=r; } int main(){int T;scanf("%d",&T);for(int TT=1;TT<=T;TT++){long long a,b,c,d,ans1=0,ans2=0;scanf("%lld%lld%lld%lld",&a,&b,&c,&d);for(int i=59;i>=0;i--){bool v10=valid(ans1,i,0,a,b),v11=valid(ans1,i,1,a,b),v20=valid(ans2,i,0,c,d),v21=valid(ans2,i,1,c,d);if(v10&&v21)ans2|=1ll<<i;else if(v11&&v20)ans1|=1ll<<i;else if(v11&&v21)ans1|=1ll<<i,ans2|=1ll<<i;}printf("%lld\n",ans1^ans2);}return 0; }

G. BZOJ 4245

給定一個長度為 \(n\) 的序列 \(a[1],a[2],\dots ,a[n]\),請將它劃分為 \(m\) 段連續的區間,設第 \(i\) 段的費用 \(c[i]\) 為該段內所有數字的異或和,則總費用為 \(c[1] | c[2] | \dots | c[m]\) 。請求出總費用的最小值。

記錄一下前綴異或和,然后枚舉一個高位,如果存在一個高位使得至少 \(m\) 個異或和為 \(0\) 且總異或和 \((prev[n])\)\(0\) ,那么即可劃分,此時這一位對答案的貢獻為 \(0\) ,否則該位對答案的貢獻為一個 \(2\) 的冪。

I. J. 字典樹在字符串上的應用,略

K. HDU 4099

\(T=50000\) 組詢問,每次給出一個長度不超過40的數,求最小的斐波那契數,使得給定的數是這個數的前綴。如果前100000個數中沒有符合條件的,輸出-1。

高精計算前100000個斐波那契數,只需存儲前50位(類似double),然后全部插到字典樹里。

轉載于:https://www.cnblogs.com/BlogOfchc1234567890/p/10885610.html

總結

以上是生活随笔為你收集整理的字典树andXOR*的全部內容,希望文章能夠幫你解決所遇到的問題。

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