1. 程式人生 > >PAT甲級1056,1057解題報告

PAT甲級1056,1057解題報告

1056 Mice and Rice (25 point(s))

Mice and Rice is the name of a programming contest in which each programmer must write a piece of code to control the movements of a mouse in a given map. The goal of each mouse is to eat as much rice as possible in order to become a FatMouse.

First the playing order is randomly decided for N​P​​ programmers. Then every N​G​​ programmers are grouped in a match. The fattest mouse in a group wins and enters the next turn. All the losers in this turn are ranked the same. Every N​G​​ winners are then grouped in the next match until a final winner is determined.

For the sake of simplicity, assume that the weight of each mouse is fixed once the programmer submits his/her code. Given the weights of all the mice and the initial playing order, you are supposed to output the ranks for the programmers.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers: N​P​​ and N​G​​ (≤1000), the number of programmers and the maximum number of mice in a group, respectively. If there are less than N​G​​ mice at the end of the player's list, then all the mice left will be put into the last group. The second line contains N​P​​ distinct non-negative numbers W​i​​ (i=0,⋯,N​P​​−1) where each W​i​​ is the weight of the i-th mouse respectively. The third line gives the initial playing order which is a permutation of 0,⋯,N​P​​−1 (assume that the programmers are numbered from 0 to N​P​​−1). All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the final ranks in a line. The i-th number is the rank of the i-th programmer, and all the numbers must be separated by a space, with no extra space at the end of the line.

Sample Input:

11 3
25 18 0 46 37 3 19 22 57 56 10
6 0 8 7 10 5 9 1 4 2 3

Sample Output:

5 5 5 2 5 5 5 3 1 3 5

題目大意:模擬淘汰賽,每ng個一場,贏的出線,輸的淘汰,給出名次。

解題思路:用佇列模擬一下,水題。

#include<iostream>
#include<string.h>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<time.h>
#include<math.h>
#include<set>
#include<list>
#include<climits>
#include<queue>
#include<cstring>
#include<map>
#include<stack>
#include<string>
using namespace std;
struct mic {
	int value;
	int rank;
};
mic t[1005];
int np[1005];
int ng[1005];
map<int, int> a;
int main()
{
	int np, ng;queue<int> cur;
	cin >> np >> ng;
	for (int i = 0; i < np; i++) {
		cin >> t[i].value;
	}
	for (int i = 0; i < np; i++) {
		int d;
		cin >> d;
		cur.push(d);
	}
	int tnp = np;
	
	while (cur.size() != 1) {
	int sumM = tnp%ng != 0 ? tnp / ng + 1 : tnp / ng;
	for (int i = 0; i < sumM; i++) {
		int k = cur.front();
		for (int j = 0; j < ng; j++) {
			if (i*ng + j >= tnp)break;
			int front = cur.front();
			if (t[front].value > t[k].value) {
				k = front;
			}
			t[front].rank = sumM + 1;
			cur.pop();
		}
		cur.push(k);
	}
	tnp = sumM;
	}
	t[cur.front()].rank = 1;
	for (int i = 0; i < np; i++) {
		if (i != np - 1)cout << t[i].rank << " ";
		else
			cout << t[i].rank << endl;
	}
	return 0;
}

1057 Stack (30 point(s))

Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic operations include Push (inserting an element onto the top position) and Pop (deleting the top element). Now you are supposed to implement a stack with an extra operation: PeekMedian -- return the median value of all the elements in the stack. With Nelements, the median value is defined to be the (N/2)-th smallest element if N is even, or ((N+1)/2)-th if N is odd.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤10​5​​). Then N lines follow, each contains a command in one of the following 3 formats:

Push key
Pop
PeekMedian

where key is a positive integer no more than 10​5​​.

Output Specification:

For each Push command, insert key into the stack and output nothing. For each Pop or PeekMedian command, print in a line the corresponding returned value. If the command is invalid, print Invalid instead.

Sample Input:

17
Pop
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
Pop
Push 5
Push 4
PeekMedian
Pop
Pop
Pop
Pop

Sample Output:

Invalid
Invalid
3
2
2
1
2
4
4
5
3
Invalid

題目大意:模擬一下棧的操作,有一個新的操作,輸出從小到大中間那個數。

解題思路:這種題目不可能真的用棧去模擬的,那用vector,一開始想著排序就好了。。。然後三個超時,那沒辦法了,很明顯,超時肯定因為排序那個部分,也就是查中間小數的操作太蠢,然後我開始思考找中間那個數的方法了。。這種,確定下標的查詢好像我的學習情況裡也就線段樹和樹狀陣列了,線段樹打打太麻煩了,不太熟練所以我就用樹狀陣列+二分搞了一下,果然過了,其實不是很懂的。。為什麼考綱裡沒有樹狀陣列的,這裡會要考。。可能還有別的不超綱方法吧。就是利用字首和的性質,用c陣列記錄不大於i的數的個數,然後二分查詢size+1/2的地方返回就實現查找了。

程式碼如下:

#include<iostream>
#include<string.h>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<time.h>
#include<math.h>
#include<set>
#include<list>
#include<climits>
#include<queue>
#include<cstring>
#include<map>
#include<stack>
#include<string>
using namespace std;
vector<int> Stack;
int c[100005];
int lowbit(int x) { return x&-x; }
void Update(int a, int value) {
	while (a < 100001) {
		c[a] += value;
		a += lowbit(a);
	}
}
int Sum(int a) {
	int s = 0;
	while (a >= 1) {
		s = s + c[a];
		a -= lowbit(a);
	}
	return s;
}
//二分查詢中間值
int find(int x) {
	int l = 0, r = 100000;
	while (l < r) {
		int mid = (l + r) / 2;
		if (Sum(mid) >= x) {
			r = mid;
		}
		else {
			l = mid + 1;
		}
	}
	return r;
}
int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		string s;
		cin >> s;
		if (s == "Pop") {
			if (Stack.size()==0)
				printf("Invalid\n");
			else {
				Update(Stack[Stack.size() - 1], -1);
				printf("%d\n",Stack[Stack.size()-1]);
				Stack.pop_back();
			}
		}
		else if (s == "Push") {
			int tmp;
			cin >> tmp;
			Stack.push_back(tmp);
			Update(tmp, 1);
		}
		else if (s == "PeekMedian") {
			if (Stack.size() == 0)printf("Invalid\n");
			else {
				printf("%d\n",find((Stack.size()+1)/2));
			}
		}
	}
	return 0;
}