usaco2016open silver2 diamond

     Diamond Collector(Silver)

奶牛Bessie很喜欢闪亮亮的东西(Baling~Baling~),所以她喜欢在她的空余时间开采钻石!她现在已经收集了N颗不同大小的钻石(N<=50,000),现在她想在谷仓的两个陈列架上摆放一些钻石。

    Bessie想让这些陈列架上的钻石保持相似的大小,所以她不会把两个大小相差K以上的钻石同时放在一个陈列架上(如果两颗钻石的大小差值为K,那么它们可以同时放在一个陈列架上)。现在给出K,请你帮Bessie确定她最多一共可以放多少颗钻石在这两个陈列架上。

 

输入格式(diamond.in:

    第一行输入两个值NK0<=K<1,000,000,000)

接下来N行,每行是一个整数,分别表示第1~N颗钻石的大小。

数据保证钻石的大小为正数且不超过1,000,000,000.

 

输出格式(diamond.out):

输出仅一个数,为Bessie能在这两个陈列架上摆的钻石总数的最大值。

 

输入样例:

7 3

10

5

1

12

9

5

14

 

输出样例:

5

================================================================

这题跟铜牌组的唯一不同就是多了一个陈列架.而我们的应对之策就是:先把钻石按大小排序,让他们呈单调上升,然后对于每一颗钻石,把它分别假设为陈列架上最小和最大的钻石,看在这两种情况下在一个陈列架上最多能放多少钻石,分别储存起来.再从左往右扫一遍,看每一点的左边的钻石中最多能放多少个;右边也同样做一遍这样的操作,保存在数组中.最后枚举每颗钻石,将它左边最大值与右边最大值相加,取所有情况的最大值即可.时间复杂度是O(n^2+n).#include

 
   

#include
#include

using namespace std;

const int SIZE = 50005;

ifstream fin("diamond.in");
ofstream fout("diamond.out");

int N, K, diamond[SIZE];

int main() {
fin >> N >> K;
for (int i = 0; i != N; ++i) {
fin >> diamond[i];
}
sort(diamond, diamond + N);
/*fout << "The values of sorted Diamond[] are:" << endl;
for (int i = 0; i != N; ++i) {
fout << diamond[i] << " ";
}
fout << endl;*/
int j;
int leftMost[SIZE];
j = 0;
for (int i = 0; i != N; ++i) {
while (j != N && diamond[i] - diamond[j] > K) {
++j;
}
leftMost[i] = j;
}
/*fout << "The values of leftMost[] are:" << endl;
for (int i = 0; i != N; ++i) {
fout << leftMost[i] << " ";
}
fout << endl;*/
int leftMax[SIZE];
for (int i = 0; i != N; ++i) {
leftMax[i] = i - leftMost[i] + 1;
if (i > 0) {
leftMax[i] = max(leftMax[i], leftMax[i - 1]);
}
}
/*fout << "The values of leftMax[] are:" << endl;
for (int i = 0; i != N; ++i) {
fout << leftMax[i] << " ";
}
fout << endl;*/
int rightMost[SIZE];
j = N - 1;
for (int i = N - 1; i != -1; --i) {
while (j != -1 && diamond[j] - diamond[i] > K) {
--j;
}
rightMost[i] = j;
}
/*fout << "The values of rightMost[] are:" << endl;
for (int i = 0; i != N; ++i) {
fout << rightMost[i] << " ";
}
fout << endl;*/
int rightMax[SIZE];
for (int i = N - 1; i != -1; --i) {
rightMax[i] = rightMost[i] - i + 1;
if (i != N - 1) {
rightMax[i] = max(rightMax[i] , rightMax[i + 1]);
}
}
/*fout << "The values of rightMax[] are:" << endl;
for (int i = 0; i != N; ++i) {
fout << rightMax[i] << " ";
}
fout << endl;*/
int ans = 0;
for (int i = 0; i != N - 1; ++i) {
ans = max(ans, leftMax[i] + rightMax[i + 1]);
}
fout << ans << endl;
return 0;
}

你可能感兴趣的:(解题报告,单调队列,USACO)