title

【JLU数据结构荣誉课】第一次上机实验

->点我进原题
-> 7-1 重复计数
-> 7-2 报数游戏
-> 7-3 算术表达式计算
-> 7-4 最喜爱的序列

7-1 重复计数 (100 分)


代码长度限制 \(16 KB\)
时间限制 \(1000 ms\)
内存限制 \(64 MB\)


Description

在一个有限的正整数序列中,有些数会多次重复出现。请你统计每个数的出现次数,然后按数字在序列中第一次出现的位置顺序输出数及其次数。

Input

第1行,1个整数 \(N\) ,表示整数的个数,\((1≤N≤50000)\)。

第2行,\(N\) 个正整数,每个整数 \(x\) 都满足 \(1 ≤ x ≤2000000000\)。

Output

若干行,每行两个用一个空格隔开的数,第一个是数列中出现的数,第二个是该数在序列中出现的次数。

Sample Input

12
8 2 8 2 2 11 1 1 8 1 13 13

Sample Output

8 3
2 3
11 1
1 3
13 2

思路

map裸题,将出现多少个数用 \(tot\) 和 \(b\) 数组记录有多少个数出现,用map记录每个数出现的次数即可。

代码

#include<cstdio>
#include<cctype>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#define rg register
#define ll long long
using namespace std;
inline ll read(){
	rg ll f = 0, x = 0;
	rg char ch = getchar();
	while(!isdigit(ch))	f |= (ch == '-'), ch = getchar();
	while( isdigit(ch))	x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
	return f? -x: x;
}
ll b[50010];
int tot = 0;
map <int, int> mp;
int main(){
	ll n = read();
	ll a[50010];
	for(rg int i = 1; i <= n; ++i){
		ll tmp = read();
		if(!mp[tmp]){
			b[++tot] = tmp;
			mp[tmp]++;
		} else	mp[tmp]++;
	}
	for(rg int i = 1; i <= tot; ++i){
		printf("%lld %lld\n", b[i], mp[b[i]]);
	}
	return 0;
}




7-2 报数游戏 (100 分)


代码长度限制 \(16 KB\)
时间限制 \(400 ms\)
内存限制 \(64 MB\)


Description

\(n\) 个人围成一圈,从 \(1\) 开始依次编号,做报数游戏。 现指定从第 \(1\) 个人开始报数,报数到第 \(m\) 个人时,该人出圈,然后从其下一个人重新开始报数,仍是报数到第 \(m\) 个人出圈,如此重复下去,直到所有人都出圈。总人数不足 \(m\) 时将循环报数。请输出所有人出圈的顺序。

Input

一行,两个整数 \(n\) 和 \(m\) 。\(n\) 表示游戏的人数,\(m\) 表示报数出圈的数字,\(1≤n≤50000\),\(1≤m≤100\).

Output

一行,\(n\) 个用空格分隔的整数,表示所有人出圈的顺序

Sample Input

5 2

Sample Output

2 4 1 5 3

思路

经典约瑟夫问题,不多解释

代码

#include<cstdio>
#include<cctype>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define rg register
#define ll long long
using namespace std;
inline int read(){
	rg int f = 0, x = 0;
	rg char ch = getchar();
	while(!isdigit(ch))	f |= (ch == '-'), ch = getchar();
	while( isdigit(ch))	x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
	return f? -x: x;
}
int main(){
	int n = read(), m = read();
	int a[50010] = {0}, cnt = n, ind = 1, num = 1;
	while(cnt){
		if(ind == n + 1)	ind = 1;
		if(a[ind]){
			ind ++;
			continue;
		}
		if(num == m){
			a[ind] = 1;
			printf("%d", ind);
			num = 1;
			cnt --;
			if(cnt)	printf(" ");
		}
		else{
			num ++;
		}
		ind ++;
	}
	return 0;
}




7-3 算术表达式计算 (100 分)


代码长度限制 \(16 KB\)
时间限制 \(400 ms\)
内存限制 \(64 MB\)


Description

任务: 计算算术表达式的值。

算术表达式按中缀给出,以 \(=\) 号结束,包括 \(+,-,\times,\div\) 四种运算和 \((\)、\()\) 分隔符。运算数的范围是非负整数,没有正负符号,小于等于 \(10^{9}\)。

计算过程中,如果出现除数为0的情况,表达式的结果为”NaN” ; 如果中间结果超出32位有符号整型范围,仍按整型计算,不必特殊处理。 输入保证表达式正确。

Input

一行,包括1个算术表达式。算术表达式的长度小于等于 \(1000\)。

Output

一行,算术表达式的值 。

Sample Input

(1+30)/3=

Sample Output

10

思路

用一个栈来存符号,另一个栈来存数字。如果是数字直接入数字栈;如果是符号,栈空则立刻入栈,是左括号立刻入栈,优先级大于上一个字符入栈,是右括号则一直弹栈运算到弹出左括号,如果优先级小于等于上一个字符,则一直运算弹栈到左括号或栈空。要特别注意优先级的判断与不合法情况的判断(除数不为0)。详情见代码。

代码

#include<cstdio>
#include<cctype>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
inline bool judpri(char a, char b){
	if((a == '*' || a == '/') && (b == '+' || b == '-'))	return 1;
	if((a == '+' || a == '-') && (b == '+' || b == '-'))	return 0;
	if((a == '+' || a == '-') && (b == '*' || b == '/'))	return 0;
	if((a == '*' || a == '/') && (b == '*' || b == '/'))	return 0;
	return 1;
}
inline int cal(int n1, char opt, int n2){
	if(opt == '+')	return n1 + n2;
	if(opt == '-')	return n1 - n2;
	if(opt == '*')	return n1 * n2;
	if(opt == '/')	return n1 / n2;
}
inline bool judcal(char opt, int num){
	if(opt == '/' && num == 0)	return 0;
	else	return 1;
}
int main(){
	char ch;
	int Q[10100];//num
	int qtop = 0;
	char C[10100];//opt
	int ctop = 0;
	int book = 0;
	scanf("%c", &ch);
	if(ch == '=')	book = 1;
//	cout << ch<<endl;
	while(!book){
//		cout << ch << endl;
		
		int num[20], tot = 0;
		int sum = 0;
		while(ch >= '0' && ch <= '9'){
//			cout << ch<<endl;
			num[++ tot] = ch - '0';
			scanf("%c", &ch);
			if(ch == '=')	book = 1;
		}
		if(tot){
			for(int i = 1; i <= tot; ++i){
				sum = sum * 10 + num[i];
			}
			Q[++qtop] = sum;
//			cout << sum << endl;
			continue;
		} 
//		cout << ch << endl;
		if(ch == ')'){
			while(C[ctop] != '(' && ctop){
				
				int n2 = Q[qtop --], c = C[ctop --], n1 = Q[qtop --];
//					cout << n1 << ' ' << c << ' ' << n2 << endl;
				if(!judcal(c, n2)){
					printf("NaN");
					return 0;
				}
				int ans = cal(n1, c, n2);
				Q[++qtop] = ans;
			}
			ctop --;
		} else if(ch == '(' || !ctop || judpri(ch, C[ctop])){
			C[++ctop] = ch;
//			putchar(ch);
		} else{
			while(ctop && C[ctop] != '('){
				int n2 = Q[qtop --], c = C[ctop], n1 = Q[qtop --];
//				cout << n1 << ' ' << c << ' ' << n2 << endl;
				if(!judcal(c, n2)){
					printf("NaN");
					return 0;
				}
				int ans = cal(n1, c, n2);
				Q[++qtop] = ans;
				ctop --;
			}
			C[++ctop] = ch;
		}
		scanf("%c", &ch);
		if(ch == '=')	book = 1;
//		cout << ch<<endl;
	}
	while(ctop){
		
		int n2 = Q[qtop --], c = C[ctop], n1 = Q[qtop --];
		if(!judcal(c, n2)){
			printf("NaN");
			return 0;
		}
		int ans = cal(n1, c, n2);
		Q[++qtop] = ans;
		ctop --;
	}
	printf("%d", Q[1]);
	return 0;
}
//(((1+2)/(1+1-1)/3)*2/2/2)+1)+1=




7-4 最喜爱的序列 (100 分)


代码长度限制 \(16 KB\)
时间限制 \(400 ms\)
内存限制 \(64 MB\)


Description

小唐这段时间在研究序列。拿来 \(n\) 个整数的序列,他给序列中的每个整数都赋予一个喜爱值。喜爱值也是整数,有正有负,越大表明越喜欢。他想知道,如何从序列中连续取最多 \(m\) 个数,他获得喜爱值最大。\(1≤n≤500000\),\(1≤m≤N\)。

Input

第一行是两个整数 \(n\), \(m\) 。分别代表序列中数的个数以及能取的最多个数。

第二行用空格隔开的 \(n\) 个整数,第 \(i\) 个整数 \(Li\) 代表他对第 \(i\) 个数的喜爱值。\(│Li│≤1000\)

Output

一行,三个数,表示获得最大喜爱值,及第一个取最大喜爱值的区间。

Sample Input

5 2
1 4 5 2 3

Sample Output

9 2 3

思路

单调队列。处理一个前缀和,单调队列中存左端点,保持从1到左端点的和单调递增,当超过区间距离时出队,每次以队头点到当前端点的区间和与答案比较,更新答案即可。

代码

#include<cstdio>
#include<cctype>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define rg register
#define ll long long
using namespace std;
inline int read(){
	rg int f = 0, x = 0;
	rg char ch = getchar();
	while(!isdigit(ch))	f |= (ch == '-'), ch = getchar();
	while( isdigit(ch))	x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
	return f? -x: x;
}
const int inf = 0x7fffffff;
int q[500010], maxn, ml, mr;
int sum[500010];
int main(){
	int n = read(), m = read();
	sum[0] = 0;
	int f = 0, r = -1;
	maxn = -inf;
	for(rg int i = 1; i <= n; ++i){
		sum[i] = sum[i - 1] + read();
	}
	for(rg int i = 1; i <= n; ++i){
		while(f <= r && q[f] < i - m)	f++;
		if(maxn < sum[i] - sum[q[f]]){
			maxn = sum[i] - sum[q[f]];
			ml = q[f] + 1;
			mr = i;
		}
		while(f <= r && sum[q[r]] >= sum[i])	r--;
		q[++r] = i;
	}
	printf("%d %d %d", maxn, ml, mr);
	return 0;
}
posted @ 2021-05-16 16:23  Horrigue_JyowYang  阅读(144)  评论(0)    收藏  举报