poj3274(Gold Balanced Lineup)

题目地址:Gold Balanced Lineup

题目大意:

一个农场有N个奶牛,每个奶牛都有不同的特征,聪明的农夫给奶牛 feature ID。代表奶牛所具有的特征。将feature ID 写成为K位的二进制的数,其中有1的位置代表奶牛具有此特征,0代表没有此特征。从i->j 使这个区间的奶牛所有特征的个数是相等的。其中最大的区间差就是题图所求的。

解题思路:

解题思路:

经典题,不转化问题很难做,先根据官方的方法转化问题,把“求最远的两行间各个特征出现次数相等”转化为“求最远的相同两行”,再用Hash查找。

这是官方解题报告——

Consider the partial sum sequence of each of the k features built by taking the

sum of all the values up to position i. The problem is equivalent to:

Given an array s[n][k], find i,j, with the biggest separation for which s[ i ]

[l]-s[j][l] is constant for all l.

The problem is now to do this efficiently. Notice that s[ i ][l]-s[j][l] being

constant for all l is equivalent to s[ i ][l]-s[j][l]=s[ i ][1]-s[j][1] for all

l, which can be rearranged to become s[ i ][l]-s[ i ][1]=s[j][l]-s[j][1] for all

l. Therefore, we can construct another array a[n][k] where a[ i ][j]=s[ i ][j]-

s[ i ][1] and the goal is to find i and j with the biggest separation for which

a[ i ][l]=a[j][l] for all l.

This can be done by sorting all the a[ i ] entries, which takes O(nklogn) time

(although in practice rarely will all k elements be compared). Another

alternative is to go by hashing, giving an O(nk) solution. Both solutions are

fairly straightforward once the final array is constructed.

大概意思就是:

数组sum[i][j]表示从第1到第i头cow属性j的出现次数。

所以题目要求等价为:

求满足

sum[i][0]-sum[j][0]=sum[i][1]-sum[j][1]=.....=sum[i][k-1]-sum[j][k-1] (j<i)

中最大的i-j

将上式变换可得到

sum[i][1]-sum[i][0] = sum[j][1]-sum[j][0]

sum[i][2]-sum[i][0] = sum[j][2]-sum[j][0]

......

sum[i][k-1]-sum[i][0] = sum[j][k-1]-sum[j][0]

令C[i][y]=sum[i][y]-sum[i][0] (0<y<k)

初始条件C[0][0~k-1]=0

所以只需求满足C[i][]==C[j][] 中最大的i-j,其中0<=j<i<=n。

C[i][]==C[j][] 即二维数组C[][]第i行与第j行对应列的值相等,

那么原题就转化为求C数组中 相等且相隔最远的两行的距离i-j

以样例为例

7 3
7
6
7
2
1
4
2
 

先把7个十进制特征数转换为二进制,并逆序存放到特征数组feature[ ][ ],得到:

7 -> 1 1 1

6 -> 0 1 1

7 -> 1 1 1

2 -> 0 1 0

1 -> 1 0 0

4-> 0 0 1

2 ->0 1 0

(行数为cow编号,自上而下从1开始;列数为特征编号,自左到右从0开始)

再求sum数组,逐行累加得,sum数组为

1 1 1

1 2 2

2 3 3

2 4 3

3 4 3

3 4 4

3 5 4

再利用C[i][y]=sum[i][y]-sum[i][0]求C数组,即所有列都减去第一列

注意C数组有第0行,为全0

0 0 0 à 第0行

0 0 0

0 1 1

0 1 1

0 2 1

0 1 0

0 1 1

0 2 1

显然第2行与第6行相等,均为011,且距离最远,距离为6-2=4,这就是所求。

需要注意:

但是最大数据有10W个,即10W行,因此不能直接枚举找最大距离,必须用Hash查找相同行,找到相同行再比较最大距离。

我哈希是将K个数求和sum%N,然后放到一个vector里,然后一一比较找出相同序列,哈希的过程中数组可能是负数,所以记得处理负数的可能。

一个疑问: 如果100000个sum%N的数想同,我代码是不是就超时了呢。

代码:

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <sstream>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <cstdio>
  7 #include <string>
  8 #include <bitset>
  9 #include <vector>
 10 #include <queue>
 11 #include <stack>
 12 #include <cmath>
 13 #include <list>
 14 //#include <map>
 15 #include <set>
 16 using namespace std;
 17 /***************************************/
 18 #define ll long long
 19 #define int64 __int64
 20 /***************************************/
 21 const int INF = 0x7f7f7f7f;
 22 const double eps = 1e-8;
 23 const double PIE=acos(-1.0);
 24 const int d1x[]= {0,-1,0,1};
 25 const int d1y[]= {-1,0,1,0};
 26 const int d2x[]= {0,-1,0,1};
 27 const int d2y[]= {1,0,-1,0};
 28 const int fx[]= {-1,-1,-1,0,0,1,1,1};
 29 const int fy[]= {-1,0,1,-1,1,-1,0,1};
 30 /*vector <int>map[N];map[a].push_back(b);int len=map[v].size();*/
 31 /***************************************/
 32 void openfile()
 33 {
 34     freopen("data.in","rb",stdin);
 35     freopen("data.out","wb",stdout);
 36 }
 37 /**********************华丽丽的分割线,以上为模板部分*****************/
 38 const int N=1999;
 39 const int MMM=100001;
 40 int n,kk;
 41 int mm;
 42 int maax;
 43 int c[N][35];
 44 typedef struct
 45 {
 46     int a[35];
 47     int sum;
 48     int m;
 49 }node;
 50 node bit[MMM];
 51 vector <node >vc[N];
 52 int cmp()
 53 {
 54     int i,j,k,h;
 55     mm=0;
 56     maax=0;
 57     for(i=0;i<N;i++)
 58        for(j=0;j<vc[i].size();j++)
 59        {
 60            node n1=vc[i][j];
 61            for(k=j+1;k<vc[i].size();k++)
 62            {
 63                node n2=vc[i][k];
 64                if (n1.sum==n2.sum)
 65                {
 66                    for(h=0;h<kk;h++)
 67                        if(n1.a[h]!=n2.a[h])
 68                            break;
 69                     if (h==kk)
 70                     {
 71                         mm=abs(n1.m-n2.m);
 72                         if (maax<mm)
 73                             maax=mm;
 74                     }
 75                }
 76            }
 77        }
 78     return 0;
 79 }
 80 int main()
 81 {
 82     while(scanf("%d%d",&n,&kk)!=EOF)
 83     {
 84         int i,j;
 85         memset(bit,0,sizeof(bit));
 86         memset(c,0,sizeof(c));
 87         int x,y;
 88         for(i=1;i<=n;i++)
 89         {
 90             scanf("%d",&x);
 91             for(j=0;j<kk;j++)
 92             {
 93                 y=x&1;
 94                 bit[i].a[j]=bit[i-1].a[j]+y;
 95                 x>>=1;
 96             }
 97         }
 98      //   int sum=0;
 99         for(i=0;i<=n;i++)
100         {
101             bit[i].sum=0;
102             x=bit[i].a[0];
103             for(j=0;j<kk;j++)
104             {
105                 bit[i].a[j]-=x;
106                 bit[i].sum+=bit[i].a[j];
107             }
108             bit[i].m=i;
109             vc[(bit[i].sum+MMM)%N].push_back(bit[i]);
110         }
111         cmp();
112         printf("%d\n",maax);
113         for(i=0;i<N;i++)
114             vc[i].clear();
115     }
116     return 0;
117 }
118 /*
119 SAMPLE      binary       add       sub
120 7 3         0 0 0
121 7    ->     1 1 1       1 1 1      0 0 0
122 6    ->     1 1 0       2 2 1      1 1 0<---
123 7    ->     1 1 1  ---> 3 3 2  --> 1 1 0   |
124 2    ->     0 1 0       3 4 2      1 2 0   |4
125 1    ->     0 0 1       3 4 3      0 1 0   |
126 4    ->     1 0 0       4 4 3      1 1 0<---
127 2    ->     0 1 0       4 5 3      1 2 0
128 7 3
129 7
130 6
131 7
132 2
133 1
134 4
135 2
136 4
137
138 7 3
139 7 7 7 7 7 7 7
140 7
141
142 4 4
143 1
144 2
145 4
146 8
147 4
148
149 4 4
150 8
151 1
152 2
153 4
154 4
155
156 5 4
157 3
158 1
159 2
160 4
161 8
162 4
163
164 1 5
165 3
166 0
167
168 1 2
169 3
170 1
171
172 1 3
173 7
174 1
175 */

 

poj3274(Gold Balanced Lineup)

时间: 2024-11-09 03:15:43

poj3274(Gold Balanced Lineup)的相关文章

poj 3274 -- Gold Balanced Lineup

Gold Balanced Lineup Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 12110   Accepted: 3553 Description Farmer John's N cows (1 ≤ N ≤ 100,000) share many similarities. In fact, FJ has been able to narrow down the list of features shared

bzoj1702[Usaco2007 Mar]Gold Balanced Lineup 平衡的队列*

bzoj1702[Usaco2007 Mar]Gold Balanced Lineup 平衡的队列 题意: N头牛,一共K种特色.每头牛有多种特色.[i,j]段被称为balanced当且仅当K种特色在[i,j]内拥有次数相同.求最大的[i,j]段长度.n≤100000,k≤30. 题解: 得到式子:a[i][l]-a[j][l]=a[i][l-1]-a[j][l-1],l在2..k之间,移项得a[i][l]-a[i][l-1]=a[j][l]-a[j][l-1],l在2..k之间,故可以定义一个

1702: [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列

1702: [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 510  Solved: 196[Submit][Status][Discuss] Description Farmer John's N cows (1 <= N <= 100,000) share many similarities. In fact, FJ has been able to narrow

poj 3274 Gold Balanced Lineup, 拉链式hash

sum[i][j] 表示从第1到第i头cow属性j的出现次数 所以题目要求等价为: 求满足 sum[i][0]-sum[j][0]=sum[i][1]-sum[j][1]=.....=sum[i][k-1]-sum[j][k-1] (j<i) 中最大的i-j 将上式变换可得到 sum[i][1]-sum[i][0] = sum[j][1]-sum[j][0] sum[i][2]-sum[i][0] = sum[j][2]-sum[j][0] ...... sum[i][k-1]-sum[i][0

【POJ 3274】Gold Balanced Lineup (stl map )设计hash表,处理碰撞

题目链接 题目链接 http://poj.org/problem?id=3274 题意 输入每头牛的特征的10进制,若i~j头牛中每个数位的特征相等则满足要求,求所有满足要求的j-i的最大值. 解题思路 抽屉原理,用前缀和处理每个数位即可. 直接暴力的话复杂度太大了,所以需要取巧的办法. 直接暴力求解是sum[i][p] - sum[j][p] == sum[i][0] - sum[j][0].其中i表示第i头牛,j表示第j头牛,p表示第p个特征,i > j. 取巧的办法:sum[i][p] -

Gold Balanced Lineup - poj 3274 (hash)

这题,看到别人的解题报告做出来的,分析: 大概意思就是: 数组sum[i][j]表示从第1到第i头cow属性j的出现次数. 所以题目要求等价为: 求满足 sum[i][0]-sum[j][0]=sum[i][1]-sum[j][1]=.....=sum[i][k-1]-sum[j][k-1] (j<i) 中最大的i-j 将上式变换可得到 sum[i][1]-sum[i][0] = sum[j][1]-sum[j][0] sum[i][2]-sum[i][0] = sum[j][2]-sum[j]

bzoj 1702: [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列【hash】

我%&&--&()&%????? 双模hashWA,unsigned long longAC,而且必须判断hash出来的数不能为0???? 我可能学了假的hash 这个题求个前缀和,然后目标是找到距离当前位置最远,且能使这两个数组差分后2-k位相同 hash把差分后数组的2到k位压起来即可,用map存这个hash值最早出现的位置 但是我还是不明白为啥hash值不能为0啊?? #include<iostream> #include<cstdio> #i

SBT(Size Balanced Tree)

1. 二叉搜索树 二叉搜索树,是一种能实现动态查询第k大或查询,某数在序列中的排名的树形结构,在数据较为随机的情况下,它的期望复杂度为O(logn),但是若是数据为一个有序序列,那么该二叉搜索树,将会变成一条链,此时每次查找的复杂度将会变成复杂度为O(n) 2. SBT 针对上述问题,为了能使复杂度回到O(logn),我们在每次插入操作后,对树形进行高效的调整使之变的较为平衡.这时树高变成logn 而搜索的复杂度也于是会变回logn为此我们引入左旋和右旋操作 void zx(int &x) {

[Usaco2007 Mar]Gold Balanced Lineup 平衡的队列

Description N(1<=N<=100000)头牛,一共K(1<=K<=30)种特色,每头牛有多种特色,用二进制01表示它的特色ID.比如特色ID为13(1101),则它有第1.3.4种特色.[i,j]段被称为balanced当且仅当K种特色在[i,j]内拥有次数相同.求最大的[i,j]段长度. Input 第一行给出数字N,K 下面N行每行给出一个数字,代表这头牛的特征值 Output 求出一个区间值,在这个区间中,所有牛的这K种特征值的总和是相等的. Sample In