상세 프로그래밍 Week4- 작업
A-DDL 공포
기술
ZJM이있다 N 작업, 각 작업은 자신의 DDL을 가지고 ZJM는 DDL 전에 일을하지 않을 경우, 다음 교사가 모든 일반적인 점을이 작업을 공제합니다. 그래서 ZJM은 가능한 한 조금 덜 포인트 버클 숙제의 순서를 정렬하는 방법을 알고 싶어요.
T 테스트 입력. 각 작업 시험 량 (1 <= N <= 1000 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, 최대 스택 DDL 작업이 같거나 X 큰 최초의 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- 네 개의 열
기술
ZJM 각 열에는 N 자리수의 숫자를 가지며, 네 개의 열 A, B, C, D를 갖는다. 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
생각
먼저, 각각 번호 B의 열거는, A + B는 각 컬럼의 숫자의 오름차순으로 열 수를 첨가 한 후, 그 반대 번호 검색에, C + D의 각각에 대해, C 및 D의 각각의 번호를 열거 열 번호에 나타나는 숫자, 즉 정렬 순서 찾을 성과 - 필요성은 첫 번째와 마지막의 두 수의 합을 찾기 위해 각각 이진 검색을 사용하는 (C + D)를 첨가 빼기 최종 합계는 다른 조합의 수이다.
요약
(C - 일 개 측면에서, 네 개의 숫자 0, (A)에 대응하고는 + B =의 합, 복잡성을 감소하고, AB는 각각 CD를 열거하며, 각 열거 번호 ABCD는 복잡도는 4 승에 도달 할 + 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과는 어레이 [i]는 새로운 어레이 ANS를 생성한다. 그것은 모든 I, J에 대한 새로운 배열로 정의하고 난 J =이되고있다 ANS [] = ABS (CAT [I] - 고양이 [J])! 1 <= I <J <= N. 이러한 새로운 배열. 평균 결정은, 그 중간의 위치 번호에 대응하는 정렬 (+ 1 렌) / 2이고, '/'라운딩이다.
입력의 복수 세트, 길이 N 고양이, 고양이 [I]의 시퀀스를 입력 한 후 입력 한 각각 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의 열거 수가 먼저 동일한보다 큰 경우 찾는 이진 검색을 사용하는 것도 가능하다 그때 계산 첨자 수 사이 + P 포지션 수와, 숫자 즉 자격 튜플 조건을 만족하고, 순위의 평균 수를 비교 모든 J 최종 합계는, 순위가 낮은 중앙값보다가 중간 오른쪽이다 중앙값은 좌측 중간 순위보다 크면 두 값이 동일한 경우 측은 새로운 배열 요소에 대응 업데이트 범위 조회 값하고, P는 중간 값이다.
각각 1,3,2,4- 수 4 가정
- 절반 답변으로 다음과 같습니다 :
요약
P 진 않음 순위 P + I 개의 열거 계산
0부터 시작 후 저장 요소가 보낸, 중앙값이 분류 코드 (+ 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);
}
}