詳細なプログラミングWeek4-ジョブ
A-DDL恐怖
説明
ZJMがありますn個のジョブは、各ジョブには、独自のDDLを持ってZJMは、DDLの前に仕事をしていない場合は、教師がすべての通常ポイントをこの仕事が差し引かれます。だから、ZJMはできるだけビット以下の点をバックルして宿題の順序を調整する方法を知りたいです。
T検定の入力。ワークの各試験量は、(1 <= N <= 1000 Nを有する )、 及びフラクショナルNジョブの入力DDL控除です。
少なくともバックルスコア各テストケースの出力。
サンプル
input:
3
3
3 3 3
10 5 1
3
1 3 1
6 2 3
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4
output:
0
3
5
考え
まず、各ジョブのカスタム構造のDDLと控除のポイントが含まれています。N個の各テストケースのためのジョブ、DDLを減少させる一次、次いでバックからフロント列挙するために、毎日、各タスクのための一日のスケジュール、X日列挙するために、配列の最初の要素から開始し、すべてのDDL = xは最大ヒープ・ジョブが完了列挙1まで追加または差し引か点、(スコア最大ヒープソート各ジョブに係るバックル)を加え、次いで、最大要素スタックからスタックの頂うち、この日に配置します日、最大ヒープはその後、空でない場合、これらのジョブはバックルスコアを追加し、延滞しています。最終的な出力合計スコアバックル
概要
問題を解決するための基本的な考え方貪欲なアルゴリズムである日はDDLを配置するために、貪欲な基準は、端から1日だけ前方である> =一日の仕事のバックルの割合の最大の仕事、控除少ないポイントを残します。
日X = X DDLにのみ添加列挙の背面から、最初のx日の最大スタックDDL動作がジョブを確保以上のXされ、DDLは、ヒープからではなく、誤って小さいジョブのリードを行いジョブタイムアウト。
コード
#include <iostream>
#include <algorithm>
#include<cstdio>
#include<cstdlib>
#include <vector>
#include<queue>
using namespace std;
int T;
struct task {
int DDL, s;
//bool operator()(const task &t) {
// return s t.s;
//}
}P[1100];
struct cmp {
bool operator()(task a, task b) {
return a.s < b.s;
}
};
bool compare(const task &a, const task &b) {
return a.DDL > b.DDL;
}
int main()
{
cin.sync_with_stdio(false);
cin >> T;
while (T--) {
int N;
cin >> N;
//memset(P, 0, sizeof(task));
//memset(s, 0, sizeof(int));
int score = 0;
for (int i = 0; i < N; i++)
cin >> P[i].DDL;
for (int i = 0; i < N; i++)
cin >> P[i].s;
sort(P, P + N,compare);
int index = 0;
priority_queue<task,vector<task>,cmp > Q;
for (int t = 1010; t >= 1; t--) {
//if (index >= N)break;
for (; index <N; index++) {
if (P[index].DDL == t) { Q.push(P[index]); }
else if (P[index].DDL < t)break;
}
if (!Q.empty()) {
task temp = Q.top();
Q.pop();
//if (temp.DDL < t) { score += temp.s; }
}
}
while (!Q.empty()) {
task temp = Q.top();
Q.pop();
score += temp.s;
/*cout << temp.s << endl;*/
}
cout << score << endl;
}
}
B- 4つの列
説明
ZJMは、4つの列A、B、C、Dを有し、各列は、桁数を有するN。ZJMそれぞれの列番号から取られた数が、彼はそのような4と0の数、そのプログラムのどのように多くの種類を知っていただきたいと思います。場合は、列の数が異なる数として扱うために、数字の同じ複数有しています。
四つの要素の列の数、異なる出力の組合せの数N。
サンプル
input:
6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45
output:
5
考え
まず、Aのそれぞれと数Bの列挙は、A + Bは、それぞれの列の数、昇順の列の数を加えた後、その反対側の番号の検索では、C + Dのそれぞれについて、C及びDのそれぞれの数を列挙する最初と最後を見つけるために、それぞれ、バイナリ検索を使用する必要性、2つの数の和を加え減算で(C + D) - 列の数、すなわち、最初と最後の位置を特定するための順序付けられたシーケンス内に現れる番号最終的な和が異なる組み合わせの数です。
概要
(C - 一の態様では、複雑さを低減するために、及びABは、それぞれCDを列挙し、各列挙番号ABCDなければならない、複雑さが第四のパワーに到達する、4個の数字0の和に等しく、A + B =に相当に+ D)。一方、この質問への鍵は、バイナリサーチの使用は、複雑さがLOGNに還元される最初の発生回数と順序付けられたシーケンスで最後に出現する、の場所を見つけることです。
コード
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
int n;
int A[4010];
int B[4010];
int C[4010];
int D[4010];
vector<int> AB;
int sum = 0;
int find1(int x) {
int l = 0, r = AB.size() - 1, ans = -1;
while (l <= r) {
int mid = l + r >> 1;
if (AB[mid] == x) {
ans = mid;
r = mid - 1;
}
else if (AB[mid] > x)r = mid - 1;
else l = mid + 1;
}
return ans;
}
int find2(int x) {
int l = 0, r = AB.size() - 1, ans = -1;
while (l <= r) {
int mid=(l + r) >> 1;
if (AB[mid] == x) {
ans = mid;
l = mid + 1;
}
else if (AB[mid] > x)r = mid - 1;
else l = mid + 1;
}
return ans;
}
int main()
{
cin.sync_with_stdio(false);
cin >> n;
for (int i = 0; i < n; i++)
cin >> A[i] >> B[i] >> C[i] >> D[i];
for(int i=0;i<n;i++)
for (int j = 0;j < n; j++)
{
AB.push_back(A[i] + B[j]);
}
sort(AB.begin(), AB.end());
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
int temp = -(C[i] + D[j]);
int first = find1(temp);
int last = find2(temp);
if (first != -1 && last != -1) { sum += last - first + 1; }
}
cout << sum << endl;
}
C-TTの神秘的な贈り物
説明
配列の猫[i]の数Nを考慮すると、新しい配列のANSを生成[i]を配列しています。これは、任意のI、Jのための新たな配列として定義され、iがjは=され、あるANS [] = ABS(猫[I] - 猫[J])] 1 <= I <J <= N. この新しい配列は、次いで、中央値は、位置番号に対応するソート(1 + LEN)/ 2であり、中央値を決定し、「/」丸めあります。
入力の複数組、長さN猫、猫[I]のシーケンスの入力後の各入力1 N、Nを発現数、<= 1E9、3 <= N <= 1E5。出力新しい配列ANS中央値
サンプル
input:
4
1 3 2 4
3
1 10 2
output:
1
8
考え
元の配列の演算範囲をこの範囲内にバイナリ回答Pを見つけ、最初の新しい配列の要素の値をソートされ、Pは、Pの各Pのビット数が新しいランキング配列を算出します。
元の列の数がソートされているため、絶対値は、Xjの<=西+ Pを与えるために行くここで計算条件を満足するインデックスjの列挙番号が最初に等しいより以上である見つけるためにバイナリサーチを用いることも可能であるiが計算される添字ができますXI + P位置の数、および条件を満足する全てのjの最終和、数字のすなわち適格タプル、及びランクの中央値を比較することは、順位中央値が中央値右未満であります側、中央値は、左側に更新範囲のルックアップ値を対応する新しいアレイエレメントメジアンランクよりも大きく、二つの数が等しい場合、次いで、Pが中央値である。場合
、それぞれ、1,3,2,4-数4を仮定し
、次のように-half答えました:
概要
Pバイナリ答え、順位PのI + 2の列挙計算
0から開始した後、記憶素子ので、中央値は、ソートコード(LEN + 1)である/ 2-1の位置番号に対応します。指定されたキーのこの質問は中央値ではない数の代わりに、[0、cat_max-cat_min]の新シリーズに属している必要があり、その要素の算出された中央の列の新しい番号を決定する方法です。比較的長いで思考にタプルの数を計算する方法。
コード
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int N;
int cat[100010];
int find(int x) {
int l = 0, r = N - 1, ans = N;
while (l <= r) {
int mid = l + r >> 1;
if (cat[mid] >= x) {
ans = mid;
r = mid - 1;
}
else if (cat[mid] > x)r = mid - 1;
else l = mid + 1;
}
return ans;
}
int main()
{
while (scanf("%d",&N)!=EOF) {
for (int i = 0; i < N; i++)
scanf("%d",&cat[i]);
sort(cat, cat + N);
int min = 0, max = cat[N - 1] - cat[0],P;
int index = (N*(N - 1) / 2 + 1) / 2-1;
//二分答案
while (min < max) {
P = (min + max) >> 1;
int pos = 0;
for (int i = 0; i < N; i++)
pos += N - find(cat[i] + P); //枚举i,计算满足条件的j的个数
if (pos >= N*(N - 1) / 2 - index)min = P + 1;
else max = P;
}
printf("%d\n", min - 1);
}
}