1. 程式人生 > 實用技巧 >Gold Balanced Lineup POJ - 3274

Gold Balanced Lineup POJ - 3274

原題連結

考察:hash+字首和

做完這道題感覺終於懂一點hash了,散列表hash是將值儲存在對映的鍵裡,會有不同值對映到相同鍵,因此必須要處理衝突

這道題牛二進位制的字首和會根據ash函式對映到相同鍵,這些字首和有些和答案要求根本不符,所以我們必須篩掉那些不符合的鍵,也就是說這道題我們不能僅僅儲存牛的字首和對映,因為有和答案不符的會對映到相同鍵,再儲存相同鍵的時候,我們必須再在相同鍵裡看牛的每一位字首和是否相同,相同的才是答案

借鑑大佬的思路:

luogu題解的分析比一些csdn的題解寫詳細多了....建議看luogu的題解.總之需要牛的每一位屬性值區間內個數相同,我們必須想到字首和思想,每一位的字首和之差相同就是個數增長相同.想到這和上面那些基本就可以做出來了

注意返回的鍵值不能為負

涉及字首和一定要考慮邊界0

這道題直接儲存下標,這樣就不用結構體記錄id

用開放地址法就是相等的時候要判斷cnt是否相同

 1 #include <iostream>
 2 #include <map>
 3 #include <vector>
 4 using namespace std;
 5 const int N = 100007;
 6 int ans,n,k;//hash 會WA的原因,不同的值會對映到相同的鍵,必須減少衝突 
 7 int cnt[N][32],h[N];
 8 vector<int> v[N];
 9
int gethash(int i) 10 { 11 int tmp = 0; 12 for(int j=1;j<=k;j++) 13 tmp = tmp*2+cnt[i][j],tmp%=N; 14 return abs(tmp)%N; 15 } 16 bool same(int i,int j) 17 { 18 for(int x=1;x<=k;x++){ 19 if(cnt[i][x]!=cnt[j][x]) return false; 20 } 21 return true; 22 } 23 int
main() 24 { 25 scanf("%d%d",&n,&k); 26 for(int i=1;i<=n;i++){ 27 int x; 28 scanf("%d",&x); 29 for(int j=1;j<=k;j++) cnt[i][j]=((x>>(j-1))&1)+cnt[i-1][j]; 30 } 31 for(int i=0;i<=n;i++){ 32 for(int j=k;j>=1;j--) cnt[i][j]-=cnt[i][1]; 33 int id = gethash(i);//得到第i頭牛的屬性和對於雜湊值 34 // printf("id==%d\n",id); 35 v[id].push_back(i);//得到i頭牛對應屬性 36 } 37 for(int i=0;i<N;i++){ 38 if(v[i].size()<2) continue; 39 for(int j=0;j<v[i].size();j++){ 40 for(int p=j+1;p<v[i].size();p++){ 41 if(same(v[i][j],v[i][p])) ans = max(ans,abs(v[i][j]-v[i][p])); 42 } 43 } 44 } 45 printf("%d\n",ans); 46 return 0; 47 }