[SCOI2009]生日礼物
小西有一条很长的彩带,彩带上挂着各式各样的彩珠。已知彩珠有N个,分为K种。简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置)。某些坐标上可以没有彩珠,但多个彩珠也可以出现在同一个位置上。 小布生日快到了,于是小西打算剪一段彩带送给小布。为了让礼物彩带足够漂亮,小西希望这一段彩带中能包含所有种类的彩珠。同时,为了方便,小西希望这段彩带尽可能短,你能帮助小西计算这个最短的长度么?彩带的长度即为彩带开始位置到结束位置的位置差。
输入描述:
第一行包含两个整数N, K,分别表示彩珠的总数以及种类数。 接下来K行,每行第一个数为Ti,表示第i种彩珠的数目。接下来按升序给出Ti个非负整数,为这Ti个彩珠分别出现的位置。
输出描述:
应包含一行,为最短彩带长度。
分析
这题类似于字符串,如果将坐标轴视为彩带,可以采用尺取法找出这段最优彩带,但是彩带的长度达到了2的31次方!而且同一个位置上可能有多种彩珠,因此这个坐标轴不能直接作为数组。应该离散化,使用结构体node记录彩珠的种类kind和位置pos,数组存放node,并根据pos进行排序,对这个数组进行尺取法。
AC
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.Arrays;
public class Main {
public static class Node {
int pos;
int kind;
Node(int kind, int pos) {
this.kind = kind;
this.pos = pos;
}
}
public static class MyCompare implements Comparator<Node> {
public int compare(Node o1, Node o2) {
return o1.pos - o2.pos;
}
}
static int[] hash;
static int K;
public static boolean check() {
for(int i = 0; i < K; ++i) {
if(hash[i] == 0)
return false;
}
return true;
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String[] strs = bf.readLine().split(" ");
int N = Integer.parseInt(strs[0]);
K = Integer.parseInt(strs[1]);
int min = Integer.MAX_VALUE;
Node[] nodes = new Node[N];
hash = new int[K];
for(int i = 0, n = 0; i < K; ++i) {
strs = bf.readLine().split(" ");
for(int j = 1; j < strs.length; ++j) {
nodes[n++] = new Node(i, Integer.parseInt(strs[j]));
}
}
Arrays.sort(nodes, new MyCompare());
int i = 0, j = 0;
while(i < N && j < N) {
++hash[nodes[j].kind];
while(i < N && check()) {
min = Math.min(min, nodes[j].pos - nodes[i].pos);
--hash[nodes[i++].kind];
}
++j;
}
System.out.println(min);
}
}
本文来自博客园,作者:brbrbr,转载请注明原文链接:https://www.cnblogs.com/brbrbr/p/15884565.html