第三周题解
第一题
寄包柜
题目描述
超市里有 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;
}
第二题
括号序列
题目描述
定义如下规则:
- 空串是「平衡括号序列」
- 若字符串 s是「平衡括号序列」,那么(s )和 s 也都是「平衡括号序列」
- 若字符串a和 b 都是「平衡括号序列」,那么 ab(两字符串拼接起来)也是「平衡括号序列」。
例如,下面的字符串都是平衡括号序列:
()
,[]
,(())
,([])
,()[]
,()[()]
而以下几个则不是:
(
,[
,]
,)(
,())
,([()
现在,给定一个仅由 (
,)
,[
,]
构成的字符串
s
s
s,请你按照如下的方式给字符串中每个字符配对:
- 从左到右扫描整个字符串。
- 对于当前的字符,如果它是一个右括号,考察它与它左侧离它最近的未匹配的的左括号。如果该括号与之对应(即小括号匹配小括号,中括号匹配中括号),则将二者配对。如果左侧未匹配的左括号不存在或与之不对应,则其配对失败。
配对结束后,对于 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,他采取如下的方法:
- 先将 11 号同学安排进队列,这时队列中只有他一个人;
- 2−N 号同学依次入列,编号为 ii 的同学入列方式为:老师指定编号为 ii 的同学站在编号为 1(i-1)1∼(i−1) 中某位同学(即之前已经入列的同学)的左边或右边;
- 从队列中去掉 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;
}