第三周题解

第三周题解

第一题

寄包柜

题目描述

超市里有 n 个寄包柜。每个寄包柜格子数量不一,第i个寄包柜有 a个格子,不过我们并不知道各个 a的值。对于每个寄包柜,格子编号从 1 开始,一直到 a。现在有 q 次操作:

  • 1 i j k:在第 i 个柜子的第 j 个格子存入物品 k。当 k=0时说明清空该格子。
  • 2 i j:查询第 i个柜子的第j个格子中的物品是什么,保证查询的柜子有存过东西。

已知超市里共计不会超过 10000000个寄包格子,ai是确定然而未知的,但是保证一定不小于该柜子存物品请求的格子编号的最大值。当然也有可能某些寄包柜中一个格子都没有。

输入格式

第一行 2 个整数 n 和 q,寄包柜个数和询问次数。

接下来 q 个整数,表示一次操作。

5 4
1 3 10000 118014
1 1 1 1
2 3 10000
2 1 1

输出格式

对于查询操作时,输出答案,以换行隔开。

118014
1

思路

利用STL里面的map方法,将两个数联合起来对应一个数(i,j对应k),当输入2时则输出i和j对应的值。

代码

#include<iostream>
#include<map>
using namespace std;
int n ,p;
map <pair<int ,int>,int> mp;
int main()
{
	cin >> n >> p;
	int num, i, j, k;
	for (int x = 0;x < p;x++)
	{
		cin >> num;
		if (num == 1)
		{
			cin >> i >> j >> k;
			mp[{i, j}] = k;
		}
		else
		{
			cin >> i >> j;
			cout << mp[{i, j}] << endl;
		}
	}
	return 0;
}

第二题

括号序列

题目描述

定义如下规则:

  1. 空串是「平衡括号序列」
  2. 若字符串 s是「平衡括号序列」,那么(s )和 s 也都是「平衡括号序列」
  3. 若字符串a和 b 都是「平衡括号序列」,那么 ab(两字符串拼接起来)也是「平衡括号序列」。

例如,下面的字符串都是平衡括号序列:

()[](())([])()[]()[()]

而以下几个则不是:

([])(())([()

现在,给定一个仅由 ()[]构成的字符串 s s s,请你按照如下的方式给字符串中每个字符配对:

  1. 从左到右扫描整个字符串。
  2. 对于当前的字符,如果它是一个右括号,考察它与它左侧离它最近未匹配的的左括号。如果该括号与之对应(即小括号匹配小括号,中括号匹配中括号),则将二者配对。如果左侧未匹配的左括号不存在或与之不对应,则其配对失败。

配对结束后,对于 s 中全部未配对的括号,请你在其旁边添加一个字符,使得该括号和新加的括号匹配。

输入格式

输入只有一行一个字符串,表示 s s s

输出格式

输出一行一个字符串表示你的答案。

样例 #1

样例输入 #1

([()

样例输出 #1

()[]()

样例 #2

样例输入 #2

([)

样例输出 #2

()[]()

提示

数据规模与约定

对于全部的测试点,保证 s s s 的长度不超过 100,且只含 ()[] 四个字符。

思路

利用两个栈,一个用来存储左括号,一个用来存储对应的坐标,再定义一个数组用来存储是否配对,如果访问到右括号,则判断栈顶元素是否配对,如果配对则数组值标记为一。最后·遍历字符串,如果未配对则直接输出()或【】,若标记为1则直接输出。

代码

#include<iostream>
#include<string>
#include<stack>
using namespace std;
stack <char> ch;
stack <int> s;
int main()
{
	string str;
	while (cin >> str)
	{
		int arr[100] = { 0 };
		for (int i = 0;i < str.length();i++)
		{
			if (str[i] == ']')
			{
				if (ch.empty())
				{

				}
				else if(ch.top()=='[')
				{
					arr[i] = 1;
					arr[s.top()] = 1;
					ch.pop();
					s.pop();
				}
			}
			else if (str[i] == ')')
			{
				if (ch.empty())
				{

				}
				else if (ch.top() == '(')
				{
					arr[i] = 1;
					arr[s.top()] = 1;
					ch.pop();
					s.pop();
				}
			}
			else
			{
				ch.push(str[i]);
				s.push(i);
			}
		}
		for (int i = 0;i < str.length();i++)
		{
			if (arr[i] == 1)
			{
				cout << str[i];
			}
			else if ((str[i] == '[') || (str[i] == ']') && arr[i] == 0)
			{
				cout << "[]";
			}
			else
			{
				cout << "()";
			}
		}
		cout << endl;
	}
	return 0;
}

第三题

后缀表达式

题目描述

所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。

输入格式

输入一行一个字符串 s*s,表示后缀表达式。

输出格式

输出一个整数,表示表达式的值。

输入输出样例

输入 #1复制

3.5.2.-*7.+@

输出 #1复制

16

思路

定义一个栈,用来存储数字,当读到运算符时提取栈内两个元素,进行相应运算然后将运算后的数存储。

代码:

#include<iostream>
#include<stack>
#include<string>
using namespace std;
stack <int> s;
int main()
{
	string str;
	cin >> str;
	int n = 0;
	for (int i = 0;i < str.length();i++)
	{
		if (str[i] == '@')
		{
			break;
		}
		else if (str[i] >= '0'&&str[i] <= '9')
		{
			n =n*10+(str[i] - '0');
		}
		else if (str[i] == '.')
		{
			s.push(n);
			n = 0;
		}
		else
		{
			int a = s.top();
			s.pop();
			int b = s.top();
			s.pop();
			if (str[i] == '+')
			{
				s.push(a + b);
			}
			else if (str[i] == '-')
			{
				s.push(b-a);
			}
			else if (str[i] == '*')
			{
				s.push(a*b);
			}
			else
			{
				s.push(b / a);
			}
		}
	}
	cout << s.top();
	return 0;
}

第四题

队列安排

题目描述

一个学校里老师要将班上 N 个同学排成一列,同学被编号为 1∼N,他采取如下的方法:

  1. 先将 11 号同学安排进队列,这时队列中只有他一个人;
  2. 2−N 号同学依次入列,编号为 ii 的同学入列方式为:老师指定编号为 ii 的同学站在编号为 1(i-1)1∼(i−1) 中某位同学(即之前已经入列的同学)的左边或右边;
  3. 从队列中去掉 M(M<N)M(M<N) 个同学,其他同学位置顺序不变。

在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。

输入格式

第 11 行为一个正整数 N,表示了有 N个同学。

第 2∼N行,第 i 行包含两个整数 k,p,其中 k 为小于 i 的正整数,p 为 0 或者 1。若 p 为00,则表示将 i 号同学插入到 k号同学的左边,p为 11 则表示插入到右边。

第 N+1 行为一个正整数 M,表示去掉的同学数目。

接下来 M行,每行一个正整数 x,表示将 x 号同学从队列中移去,如果 x 号同学已经不在队列中则忽略这一条指令。

输出格式

1行,包含最多 N 个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。

输入输出样例

输入 #1复制

4
1 0
2 1
1 0
2
3
3

输出 #1复制

2 4 1

思路

定义一个链,存储他左边的数和右边的数,如果是0,则把k的做边的数定义为i,i的右边为k,i的左边为k原来的左边,k原来的左边的右边变为i,以此类推,删除则是将x的左边的右边变为x的右边,x的右边变为x的左边,最后输出。

代码

#include<iostream>
using namespace std;
struct List
{
	int R;
	int L;
};
int main()
{
	int n, m;
	cin >> n;
	int k, p;
	List list[100000];
	int vis[100000] = {0};
	list[1].L = -1;
	list[1].R = -1;
	int front = 1;
	int end = 1;
	for (int i = 2;i <= n;i++)
	{
		cin >> k >> p;
		if (!p)
		{
			if (k == front)
			{
				front = i;
				list[i].R = k;
				list[i].L = -1;
				list[k].L = i;
			}
			else
			{
				list[i].R = k;
				list[i].L = list[k].L;
				list[list[k].L].R = i;
				list[k].L = i;
			}
		}
		else
		{
			if (k == end)
			{
				end = i;
				list[i].L = k;
				list[i].R = -1;
				list[k].R = i;
			}
			else
			{
				list[i].L = k;
				list[i].R = list[k].R;
				list[list[k].R].L = i;
				list[k].R = i;
			}
		}
	}
	cin >> m;
	for (int i = 0;i < m;i++)
	{
		int x;
		cin >> x;
		if (vis[x])
		{

		}
		else
		{
			if (x == front)
			{
				front = list[x].R;
				list[list[x].R].L = -1;
			}
			else if (x==end)
			{
				end = list[x].L;
				list[list[x].L].R = -1;
			}
			else
			{
				list[list[x].L].R = list[x].R;
				list[list[x].R].L = list[x].L;
			}
			vis[x] = 1;
		}
	}
	int i = front;
	while (i!=end)
	{
		cout << i << " ";
		i = list[i].R;
	}
	cout << i;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值