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  阅读(102)  评论(0编辑  收藏  举报