1-1题目描述
超市里有 n(1≤n≤105) 个寄包柜。每个寄包柜格子数量不一,第 i个寄包柜有 a_i(1≤a_i*≤10^5) 个格子,不过我们并不知道各个 a_i 的值。对于每个寄包柜,格子编号从 1 开始,一直到 a_i。现在有 q(1≤q≤10^5) 次操作:
-
1 i j k
:在第 i 个柜子的第 j 个格子存入物品 k(0≤k≤10^9)。当 k=0 时说明清空该格子。 -
2 i j
:查询第 i个柜子的第 j 个格子中的物品是什么,保证查询的柜子有存过东西。
已知超市里共计不会超过 10^7个寄包格子,a_i 是确定然而未知的,但是保证一定不小于该柜子存物品请求的格子编号的最大值。当然也有可能某些寄包柜中一个格子都没有。
输入格式
第一行 2 个整数 n 和 q,寄包柜个数和询问次数。
接下来 q 个整数,表示一次操作。
输出格式
对于查询操作时,输出答案,以换行隔开。
输入输出样例
输入 #1复制
5 4 1 3 10000 118014 1 1 1 1 2 3 10000 2 1 1
输出 #1复制
118014 1
说明/提示
\text{upd 2022.7.26}upd 2022.7.26:新增加一组 Hack 数据。
解题思路:构建一个二维map函数,表示第i个柜子的第j个格子
完整代码如下:
#include <bits/stdc++.h> using namespace std; const int maxn=1e5+5; map<int,map<int,int> > m; //等价map<int,int> m[maxn] // 对二维map函数的构建 int main() { int n,q; cin>>n>>q; int x,y,z,t; while(q--){ cin>>t; if(t==1){ cin>>x>>y>>z; m[x][y]=z; //直接将物品存入指定位置 }else{ cin>>x>>y; cout<<m[x][y]<<endl; } //访问指定位置,输出物品数量 } return 0; }
1-2题目描述
定义如下规则:
-
空串是「平衡括号序列」
-
若字符串 S 是「平衡括号序列」,那么 [S]和 {S} 也都是「平衡括号序列」
-
若字符串 A 和 B 都是「平衡括号序列」,那么 AB(两字符串拼接起来)也是「平衡括号序列」。
例如,下面的字符串都是平衡括号序列:
()
,[]
,(())
,([])
,()[]
,()[()]
而以下几个则不是:
(
,[
,]
,)(
,())
,([()
现在,给定一个仅由 (
,)
,[
,]
构成的字符串 $s$,请你按照如下的方式给字符串中每个字符配对:
-
从左到右扫描整个字符串。
-
对于当前的字符,如果它是一个右括号,考察它与它左侧离它最近的未匹配的的左括号。如果该括号与之对应(即小括号匹配小括号,中括号匹配中括号),则将二者配对。如果左侧未匹配的左括号不存在或与之不对应,则其配对失败。
配对结束后,对于 s 中全部未配对的括号,请你在其旁边添加一个字符,使得该括号和新加的括号匹配。
输入格式
输入只有一行一个字符串,表示 s
输出格式
输出一行一个字符串表示你的答案。
样例 #1
样例输入 #1
([()
样例输出 #1
()[]()
样例 #2
样例输入 #2
([)
样例输出 #2
()[]()
提示
数据规模与约定
对于全部的测试点,保证 s 的长度不超过 100,且只含 (
,)
,[
,]
四个字符。
解题思路:栈
先遍历字符串s,如果碰到左括号,存入栈中,并在b数组中存入它的匹配号,
如果碰到右括号,
判断栈内是否有东西:
1无 在b数组中存入它的匹配号
2有,
则判断栈顶是否有与其匹配的左括号:
1有 弹栈、对b数组相应位置(右括号,匹配的左括号)进行标记
2无 在b数组中存入它的匹配号
输出:对于b[i]中标记的,输出相应的s[i]
b[i]数组中有左括号的,先输出b[i]再输出s[i]
不然先输出s[i]再输出b[i]
注意:=和==一定要分清楚(别问我是怎么知道的qwq
完整代码如下:
#include <bits/stdc++.h> using namespace std; char s[105],b[105]; stack<int> m; //建立一个栈 int main() { cin>>s; int len=strlen(s); for(int i=0; i<len; i++){ if(s[i]=='('){ m.push(i); b[i]=')'; continue; } if(s[i]=='['){ m.push(i); b[i]=']'; continue; } //对左括号的处理 if(m.empty()|| s[i]==')' && s[m.top()]=='[' || s[i]==']' && s[m.top()]=='('){ if(s[i]==']') b[i]='['; else b[i]='('; }else{ b[m.top()]=' '; b[i]=' '; m.pop(); } //对右括号的处理 } for(int i=0; i<len; i++){ if(b[i]==' ') cout<<s[i]; else if(b[i]=='[' || b[i]=='(') cout<<b[i]<<s[i]; else cout<<s[i]<<b[i]; } return 0; }
1-3题目描述
所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。
如:3(5-2)+7 对应的后缀表达式为3.5.2.-7.+@在该式中,@
为表达式的结束符号。.
为操作数的结束符号。
输入格式
输入一行一个字符串 s,表示后缀表达式。
输出格式
输出一个整数,表示表达式的值。
样例 #1
样例输入 #1
3.5.2.-*7.+@
样例输出 #1
16
提示
数据保证,1 <=|s|<= 50,答案和计算过程中的每一个值的绝对值不超过 10^9。
解题思路:以字符串的形式输入
碰到".",将前面的数字存入栈中
碰到运算符,取出栈顶的俩个数进行运算,再把结果存入栈中
最后栈中留下的那个数就是答案
完整代码:
#include <bits/stdc++.h> using namespace std; stack<int> m; int main() { char c,s[10005]; int k=0; while((c=getchar())!='@'){ s[k++]=c; } int len=strlen(s); int sum=0,cnt,t1,t2; for(int i=0; i<len; i++){ if(s[i]>='0' && s[i]<='9'){ sum=sum*10+(s[i]-'0'); }//将字符串转化为数字 if(s[i]=='.'){ m.push(sum); sum=0; }//存入栈 if(s[i]=='+'){ t1=m.top(); m.pop(); t2=m.top(); m.pop(); cnt=t1+t2; m.push(cnt); } if(s[i]=='-'){ t1=m.top(); m.pop(); t2=m.top(); m.pop(); cnt=t2-t1; m.push(cnt); } if(s[i]=='*'){ t1=m.top(); m.pop(); t2=m.top(); m.pop(); cnt=t1*t2; m.push(cnt); } if(s[i]=='/'){ t1=m.top(); m.pop(); t2=m.top(); m.pop(); cnt=t2/t1; m.push(cnt); } }//进行运算 cout<<m.top(); return 0; }
1-4题目描述
一个学校里老师要将班上 N 个同学排成一列,同学被编号为 1~N,他采取如下的方法:
-
先将 1 号同学安排进队列,这时队列中只有他一个人;
-
2~N 号同学依次入列,编号为 i 的同学入列方式为:老师指定编号为 i 的同学站在编号为 1~(i-1)中某位同学(即之前已经入列的同学)的左边或右边;
-
从队列中去掉 M(M<N) 个同学,其他同学位置顺序不变。
在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。
输入格式
第 1 行为一个正整数 N,表示了有 N 个同学。
第 2~N行,第 i 行包含两个整数 k,p,其中 k 为小于 i 的正整数,p 为 0 或者 1。若 p 为 0,则表示将 i 号同学插入到 k 号同学的左边,p 为 1 则表示插入到右边。
第 N+1行为一个正整数 M,表示去掉的同学数目。
接下来 M行,每行一个正整数 x,表示将 x 号同学从队列中移去,如果 x号同学已经不在队列中则忽略这一条指令。
输出格式
1 行,包含最多 N 个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。
样例 #1
样例输入 #1
4 1 0 2 1 1 0 2 3 3
样例输出 #1
2 4 1
提示
样例解释:
将同学 2 插入至同学 1 左边,此时队列为:
2 1
将同学 3 插入至同学 2 右边,此时队列为:
2 3 1
将同学 4插入至同学 1左边,此时队列为:
2 3 4 1
将同学3从队列中移出,此时队列为:
2 4 1
同学 3已经不在队列中,忽略最后一条指令
最终队列:
2 4 1
数据范围
对于 20% 的数据,有 1<=N<=10;
对于 40% 的数据,有 1<=N<=1000;
对于 100%的数据,有 1<=N,M<=100000。
解题思路:双向链表(此处用数组模拟)
初始化:从零节点开始
插入:假设将k插入i的右边(拿小盆友手牵手做比方) 最后形成i,k,j
先将k的左手牵i,k的右手牵i的右手原来牵的人
再i的右手牵k,k的右手牵的人的左手牵k
插入i的左边同理
移除:标记要移除的人
输出:for(int i=a[0].r;i;i=a[i].r)
从零节点的右开始到零节点结束
完整代码如下:
#include <bits/stdc++.h> using namespace std; const int maxn=1e5+5; struct stu{ int l,r; int d;//标记是否输出 }a[maxn]={0}; void add(int i,int k,int p); int main() { a[0].r=0,a[0].l=0; add(1,0,1);//链的初始化 int n; cin>>n; int k,p; for(int i=2; i<=n; i++){ cin>>k>>p; add(i,k,p);//新增的同学 } int m,x; cin>>m; while(m--){ cin>>x; a[x].d=1; } //删除的同学 for(int i=a[0].r;i;i=a[i].r){ if(a[i].d==0) cout<<i<<" "; } return 0; } void add(int i,int k,int p) { if(p==0){ //插左 a[i].l=a[k].l; a[i].r=k; a[k].l=i; a[a[i].l].r=i; }else{ //插右 a[i].l=k; a[i].r=a[k].r; a[k].r=i; a[a[i].r].l=i; } }