首页 写随笔

cdcq(本博客废弃!现用博客:https://www.cnblogs.com/cdcq/)

本博客废弃!现用博客:https://www.cnblogs.com/cdcq/

导航

【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 }
View Code

 

posted on 2017-01-21 10:16  cdcq_old  阅读(172)  评论(0编辑  收藏  举报