poj 3274(sum矩陣+sort)

Gold Balanced Lineup
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 11195   Accepted: 3305

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 by his cows to a list of onlyK different features (1 ≤ K ≤ 30). For example, cows exhibiting feature #1 might have spots, cows exhibiting feature #2 might prefer C to Pascal, and so on.

FJ has even devised a concise way to describe each cow in terms of its "feature ID", a single K-bit integer whose binary representation tells us the set of features exhibited by the cow. As an example, suppose a cow has feature ID = 13. Since 13 written in binary is 1101, this means our cow exhibits features 1, 3, and 4 (reading right to left), but not feature 2. More generally, we find a 1 in the 2^(i-1) place if a cow exhibits featurei.

Always the sensitive fellow, FJ lined up cows 1..N in a long row and noticed that certain ranges of cows are somewhat "balanced" in terms of the features the exhibit. A contiguous range of cowsi..j is balanced if each of the K possible features is exhibited by the same number of cows in the range. FJ is curious as to the size of the largest balanced range of cows. See if you can determine it.

Input

Line 1: Two space-separated integers, N andK.
Lines 2..N+1: Line i+1 contains a single K-bit integer specifying the features present in cowi. The least-significant bit of this integer is 1 if the cow exhibits feature #1, and the most-significant bit is 1 if the cow exhibits feature #K.

Output

Line 1: A single integer giving the size of the largest contiguous balanced group of cows.

Sample Input

7 3
7
6
7
2
1
4
2

Sample Output

4

Hint

In the range from cow #3 to cow #6 (of size 4), each feature appears in exactly 2 cows in this range

Source



這道題目非常有意思。充分考察了對於sum預處理的理解(求0-i的sum). 考察了操作符重載和sort。

1.先將輸入轉化爲矩陣,'1'表示有該特徵,’0'表示沒有該特徵:

cow:    0 1 2 3 4 5 6 7

特徵1: 0 1 0 1 0 1 0 0

特徵2: 0 1 1 1 1 0 0 1

特徵3: 0 1 1 1 0 0 1 0


2.然後預處理出從位置0到位置i的所有特徵的總數:

cow:    0 1 2 3 4 5 6 7

特徵1: 0 1 1 2 2 3 3 3

特徵2: 0 1 2 3 4 4 4 5

特徵3: 0 1 2 3 3 3 4 4

那麼,我們可以想到,在上面的矩陣中,如果第j列與第i列相比,如果每個特徵的差值都相同,那麼顯然從i 到 j 就是一個滿足要求的range。比如2-6,所有特徵都差2.那麼2-6就是一個符合要求的range。


3.那麼我們進一步轉化,將每一列都最小化,即都減去各列最小的那個值。這樣判斷的時候,只需要判斷相等即可。

cow:    0 1 2 3 4 5 6 7

特徵1: 0 0 0 0 0 0 0 0

特徵2: 0 0 1 1 2 1 1 2

特徵3: 0 0 1 1 1 0 1 1


4.這樣就非常簡單啦。

發現第0, 1列是相等的,第2,3,6列是相等的, 第4,7列是相等的

那麼我們的任務再轉化爲取值相等的列裏面,列標相差最大的兩個值的差,就是最後的答案。

這個例子中,6-2=4 差值最大。就選它了。


總結這類問題的思路:

輸入預處理->求sum矩陣->sum矩陣歸一化->sort

因爲只有sort後,才能更快地查找。


提交記錄:

1.Wrong Answer. 切記!排序後遍歷,跳出循環後,還要再加一個判斷,這樣才能保證最後的那個元素也被考慮在內。

  下面的最後一行:

    int result = 0;
    int left = c[0].num, right = c[0].num;
    for (i = 1; i <= n; i++) {
        if (!equal(c[i-1], c[i])) {
            if (right-left > result) result = right-left;
            left = c[i].num;    
            right = c[i].num;
        }
        else right = c[i].num;
    }
    if (right - left > result) result = right - left;

2.Accepted!

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define oo 0x3f3f3f3f
#define MAX_N 30010
#define MAX_M 510
using namespace std;
int n, k;
struct charactor_total {
    int ck[40];
    int num;
};
charactor_total c[100010];
bool operator < (const charactor_total & a, const charactor_total & b) {
    for (int i = 0; i < k; i++) {
        if (a.ck[i] < b.ck[i]) return true;
        else if (a.ck[i] > b.ck[i]) return false;
    }
    if (a.num < b.num) return true;
    else return false;
}
bool equal (const charactor_total & a, const charactor_total & b) {
    for (int i = 0; i < k; i++) {
        if (a.ck[i] != b.ck[i]) return false;
    }
    return true;
}
int main() {
    int i, j;
    scanf("%d%d", &n, &k);
    int a[6];
    int sum[40] = {0};
    for (i = 1; i <= n; i++) {
        int id;
        scanf("%d", &id);
        for (j = 0; j < k; j++) {
            c[i].ck[j] = (int)(id & 1);
            id >>= 1;
        }
        c[i].num = i;
        int m = oo;
        for (j = 0; j < k; j++) {
            sum[j] += c[i].ck[j];
            if (sum[j] < m) {m = sum[j];}
        }
        for (j = 0; j < k; j++) {
            c[i].ck[j] = sum[j] - m;
        }
    }
    sort(c, c+n+1);
    int result = 0;
    int left = c[0].num, right = c[0].num;
    for (i = 1; i <= n; i++) {
        if (!equal(c[i-1], c[i])) {
            if (right-left > result) result = right-left;
            left = c[i].num;    
            right = c[i].num;
        }
        else right = c[i].num;
    }
    if (right - left > result) result = right - left;
    cout << result << endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章