您的位置:首页 > 其它

poj 3274 自定义排序

2015-09-03 22:13 295 查看
题意:n头牛站一排,每个牛有k个属性,每个属性有两种取值:1或0。(1表示拥有该属性,0表示没有),用位来保存属性,属性≤30个。要求找一个牛的最长连续队伍(子段),这个队伍中拥有每个属性的牛的个数相同。

思路:看数据量n^2肯定不行,想不出来,看了眼官方的解法大致明白。

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
[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
[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]数组,记录前i个牛的第j个属性和。我们用我们需要寻找sum中的两行,这两行中所有对应位的差都相等,则这段牛是符合条件的答案之一。所以我们用另一数组,来记录sum中对应行的各个元素之间的差异。我们记录c[i][j] = sum[i][j] - sum[i][0]这样只要c的两行对应相等即可。然后我们就找相隔最远的两个c的相等行即为所求。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
using namespace std;
#define clc(s,t) memset(s,t,sizeof(s))
#define INF 0x3fffffff
#define N 100005
int n,k;
struct node{
int id;
int d[32];
}s
;
int cmp(node a,node b){
for(int i = k-1;i>=0;i--){
if(a.d[i] < b.d[i])
return 1;
if(a.d[i] > b.d[i])
return 0;
}
return a.id < b.id;
}
int equal(int a,int b){
for(int i = k-1;i>=0;i--)
if(s[a].d[i] != s[b].d[i])
return 0;
return 1;
}
int main(){
int i,j,x,res=0;
scanf("%d %d",&n,&k);
for(i = 1;i<=n;i++){
scanf("%d",&x);
s[i].id = i;
for(j = 0;j<k;j++){
s[i].d[j] = x&1;
if(i>1)
s[i].d[j] += s[i-1].d[j];
x>>=1;
}
}
for(i = 1;i<=n;i++){
x = s[i].d[0];
for(j = 0;j<k-1;j++)
s[i].d[j] -= s[i].d[j+1];
s[i].d[k-1] -= x;
}
clc(s[0].d,0);
s[0].id = 0;
sort(s,s+n+1,cmp);
for(i = 0;i<=n;){
for(j = i+1;j<=n&&equal(i,j);j++);
res = max(res,s[j-1].id-s[i].id);
i = j;
}
printf("%d\n",res);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: