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;
}

猜你喜欢

转载自blog.csdn.net/TateBrwonJava/article/details/83213188
今日推荐