zoukankan      html  css  js  c++  java
  • poj3274Gold Balanced Lineup

    http://poj.org/problem?id=3274

    网上题解

    数组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

    View Code
     1 #include <iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 #define size 200010
     8 #define MOD 97777
     9 int sum[100010][31],c[100010][31],t,head[size+10],next[size+10],v[size+10];
    10 void init()
    11 {
    12     t = 0;
    13     memset(head,-1,sizeof(head));
    14 }
    15 void add(int a,int b)
    16 {
    17     next[t] = head[a];
    18     head[a] = t;
    19     v[t] = b;
    20     t++;
    21 }
    22 int main()
    23 {
    24     int i,j,k,n,g,x,bi[31];
    25     while(cin>>n>>k)
    26     {
    27         init();
    28         memset(sum,0,sizeof(sum));
    29         memset(c,0,sizeof(c));
    30         for(i = 1; i <= n ; i++)
    31         {
    32             cin>>x;
    33             g = 0;
    34             while(x)
    35             {
    36                 g++;
    37                 j = x%2;
    38                 sum[i][g]=j;
    39                 x = x/2;
    40             }
    41             for(j = 1 ; j <= k  ; j++)
    42             sum[i][j]+=sum[i-1][j];
    43         }
    44         int mi = 0;
    45         for(i = 1; i <= n ; i++)
    46         {
    47             int s = 0;
    48             for(j = 2 ; j <= k ;j++)
    49             {
    50                 c[i][j] = sum[i][j]-sum[i][1];
    51                 s = c[i][j]*j;//哈希
    52             }
    53             for(j = 2 ; j <= k ;j++)
    54                 if(c[i][j]!=0)  break;
    55             if(j==k+1&&mi<i) mi = i;
    56             s = s%MOD;
    57             if(s<0) s+=MOD;
    58             int flag = 0,a;
    59             for(j = head[s] ; j!=-1 ; j = next[j])//解决冲突
    60             {
    61                 flag = 1;
    62                 for(a = 2 ; a <= k  ; a++)
    63                 {
    64                     if(c[i][a]!=c[v[j]][a])
    65                     {
    66                         flag = 0;
    67                         break;
    68                     }
    69                 }
    70                 if(flag&&mi<i-v[j])
    71                 mi = i-v[j];
    72             }
    73             add(s,i);
    74         }
    75         cout<<mi<<endl;
    76     }
    77     return 0;
    78 }
  • 相关阅读:
    LeetCode-018-四数之和
    LeetCode-017-电话号码的字母组合
    LeetCode-016-最接近的三数之和
    LeetCode-015-三数之和
    LeetCode-014-最长公共前缀
    LeetCode-013-罗马数字转整数
    LeetCode-012-整数转罗马数字
    LeetCode-011-盛最多水的容器
    LeetCode-010-正则表达式匹配
    [leetcode]103. Binary Tree Zigzag Level Order Traversal二叉树Z形遍历
  • 原文地址:https://www.cnblogs.com/shangyu/p/2871289.html
Copyright © 2011-2022 走看看