POJ 刷题系列:3274. Gold Balanced Lineup
传送门:3274. Gold Balanced Lineup
题意:
官方题解:
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 -sj for all
l, which can be rearranged to become s[ i ][l]-s i =s[j][l]-sj for all
l. Therefore, we can construct another array a[n][k] where a[ i ][j]=s[ i ][j]-
s i 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][L],同时减去sum[i][0]之后,得到一个数组C[i][L], 如果符合黄金平衡,就能找到c[i][L] == c[j][L] for all L,此时我们就可以考虑hash,快速的把c[i][L],for all L进行散列映射,如果c[j][L] for all L 的 散列地址和c[i][L],for all L的散列地址相等,那么它可能就是候选的黄金平衡区间,更新一波最大值。
代码如下:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
public class Main{
String INPUT = "./data/judge/201802/P3274.txt";
public static void main(String[] args) throws IOException {
new Main().run();
}
int mod = 99997;
List<Integer>[] hash = new ArrayList[mod];
int n, m = 0;
int[][] c = new int[100001][31];
int[][] sum = new int[100001][31];
boolean cmp(int x, int y) {
int t = 0;
while (c[x][t] == c[y][t] && t < m) t++;
return t == m ? true : false;
}
void read() {
n = ni();
m = ni();
sum = new int[100001][31];
c = new int[100001][31];
for (int i = 0; i < mod; ++i) hash[i] = new ArrayList<Integer>();
for (int i = 1; i <= n; ++i) {
int lo = ni();
for (int j = 0; j < m; ++j) {
int x = lo % 2;
lo >>= 1;
sum[i][j] = sum[i - 1][j] + x;
}
}
for (int i = 0; i <= n; ++i) {
int su = 0;
for (int j = 0; j < m; ++j) {
c[i][j] = sum[i][j] - sum[i][0];
su = su % mod + c[i][j] << 2;
su = su % mod;
}
if (su < 0) su *= -1;
hash[su].add(i);
}
int ma = 0;
for (int i = 0; i < mod; ++i) {
if (hash[i].size() > 1) {
for (int j = 0; j < hash[i].size() - 1; ++j) {
for (int k = j + 1; k < hash[i].size(); ++k) {
if (cmp(hash[i].get(j), hash[i].get(k)) && hash[i].get(k) - hash[i].get(j) > ma) {
ma = hash[i].get(k) - hash[i].get(j);
}
}
}
}
}
out.println(ma);
}
FastScanner in;
PrintWriter out;
void run() throws IOException {
boolean oj;
try {
oj = ! System.getProperty("user.dir").equals("F:\\oxygen_workspace\\Algorithm");
} catch (Exception e) {
oj = System.getProperty("ONLINE_JUDGE") != null;
}
InputStream is = oj ? System.in : new FileInputStream(new File(INPUT));
in = new FastScanner(is);
out = new PrintWriter(System.out);
long s = System.currentTimeMillis();
read();
out.flush();
if (!oj){
System.out.println("[" + (System.currentTimeMillis() - s) + "ms]");
}
}
public boolean more(){
return in.hasNext();
}
public int ni(){
return in.nextInt();
}
public long nl(){
return in.nextLong();
}
public double nd(){
return in.nextDouble();
}
public String ns(){
return in.nextString();
}
public char nc(){
return in.nextChar();
}
class FastScanner {
BufferedReader br;
StringTokenizer st;
boolean hasNext;
public FastScanner(InputStream is) throws IOException {
br = new BufferedReader(new InputStreamReader(is));
hasNext = true;
}
public String nextToken() {
while (st == null || !st.hasMoreTokens()) {
try {
st = new StringTokenizer(br.readLine());
} catch (Exception e) {
hasNext = false;
return "##";
}
}
return st.nextToken();
}
String next = null;
public boolean hasNext(){
next = nextToken();
return hasNext;
}
public int nextInt() {
if (next == null){
hasNext();
}
String more = next;
next = null;
return Integer.parseInt(more);
}
public long nextLong() {
if (next == null){
hasNext();
}
String more = next;
next = null;
return Long.parseLong(more);
}
public double nextDouble() {
if (next == null){
hasNext();
}
String more = next;
next = null;
return Double.parseDouble(more);
}
public String nextString(){
if (next == null){
hasNext();
}
String more = next;
next = null;
return more;
}
public char nextChar(){
if (next == null){
hasNext();
}
String more = next;
next = null;
return more.charAt(0);
}
}
static class D{
public static void pp(int[][] board, int row, int col) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
sb.append(board[i][j] + (j + 1 == col ? "\n" : " "));
}
}
System.out.println(sb.toString());
}
public static void pp(char[][] board, int row, int col) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
sb.append(board[i][j] + (j + 1 == col ? "\n" : " "));
}
}
System.out.println(sb.toString());
}
}
static class ArrayUtils {
public static void fill(int[][] f, int value) {
for (int i = 0; i < f.length; ++i) {
Arrays.fill(f[i], value);
}
}
public static void fill(int[][][] f, int value) {
for (int i = 0; i < f.length; ++i) {
fill(f[i], value);
}
}
public static void fill(int[][][][] f, int value) {
for (int i = 0; i < f.length; ++i) {
fill(f[i], value);
}
}
}
static class Num{
public static <K> void inc(Map<K, Integer> mem, K k) {
if (!mem.containsKey(k)) mem.put(k, 0);
mem.put(k, mem.get(k) + 1);
}
}
}