【BZOJ1702】[usaco2007margold]队列平衡
原来蛤习线性探测的时候要每次加一个稍大一点的数而不是每次+1……连蛤习都不会写,我tmd是有多弱
原题:
N(1<=N<=100000)头牛,一共K(1<=K<=30)种特色,
每头牛有多种特色,用二进制01表示它的特色ID。比如特色ID为13(1101),则它有第1、3、4种特色。
所以,我们认为第i头牛有第J个特色,那么整数k的二进制的第j位 肯定是 1.
[i,j]段被称为平衡当且仅当K种特色在[i,j]内拥有 次数相同。
求能够平衡的最大的[i,j]段的长度。
这题附近都是蛤习,所以就往蛤习方面想了
然后想了一段时间无果,决定看题解,看了几个题解都没看懂,但是受到启发,最终脑补出正解
首先每一位求一下前缀和,两组前缀和相减就可以求得一段区间内的个数,然后给相邻两个前缀和做差,如果有两组前缀和元素之间的差都相等,这两组前缀和做差就可以使中间的值相等
恩可以这么理解,如果两组前缀和元素之间的差相等,那么一组前缀的每个元素到另一组前缀和的对应元素的delta是一样的(因为从一组到另一组相对差没变),这两组前缀和减一下,每个元素的差都相等(感觉有点差分的意思?)
然后有一些细节需要注意
首先需要设置一组全部为零的前缀和或前缀和的差,因为可能出现某一组前缀和里面所有元素都相等,这个时候就要和0减
因为添加元素0进去了,这时候0就有意义了,hash的初值就不能设成0
以及蛤习线性探测的时候要每次加一个稍大一点的数而不是每次+1
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 int read(){int z=0,mark=1; char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')mark=-1; ch=getchar();} 9 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 10 return z*mark; 11 } 12 int n,m,s[110000][50]; 13 int difference[110000][50]; 14 int maxx=0; 15 int hash[510000],ha_top=159787; 16 bool check(int x,int y){ 17 for(int i=2;i<=m;i++) if(difference[x][i]!=difference[y][i]) return false; 18 return true; 19 } 20 int get_hash(int x){ 21 int z=0; 22 for(int i=2;i<=m;i++) z=(z+difference[x][i]*94406+5195)%ha_top; 23 while(hash[z]!=-1 && !check(hash[z],x)){ z+=283; if(z>ha_top)z%=ha_top;} 24 if(hash[z]==-1){ hash[z]=x; return x;} 25 return hash[z]; 26 } 27 void get_s(int x,int y){ for(int i=1;y;i++,y>>=1) s[x][i]+=y&1;} 28 int main(){//freopen("ddd.in","r",stdin); 29 memset(s,0,sizeof(s)); 30 memset(difference,0,sizeof(difference)); 31 memset(hash,-1,sizeof(hash)); 32 cin>>n>>m; 33 get_hash(0); 34 for(int i=1;i<=n;i++){ 35 get_s(i,read()); 36 for(int j=1;j<=m;j++) s[i][j]+=s[i-1][j],difference[i][j]=s[i][j]-s[i][j-1]; 37 maxx=max(maxx,i-get_hash(i)); 38 } 39 /*for(int i=1;i<=n;i++){ 40 for(int j=1;j<=m;j++) cout<<s[i][j]<<" "; 41 cout<<endl; 42 } 43 cout<<endl; 44 for(int i=1;i<=n;i++){ 45 for(int j=1;j<=m;j++) cout<<difference[i][j]<<" "; 46 cout<<endl; 47 }*/ 48 cout<<maxx<<endl; 49 return 0; 50 }