week 3

目录

1.寄包柜

题目

输入格式

输出格式

输入样例:

输出样例:

题解

代码

2.括号序列

题目

输入格式

输出格式

输入输出样例:

说明/提示

题解

代码 

3.后缀表达式

题目

输入格式

输出格式

输入输出样例

说明/提示

题解

代码

4.队列安排

题目

输入格式

输出格式

输入输出样例

说明/提示

题解

代码


1.寄包柜

题目

超市里有 n(1\le n\le10^5)n(1≤n≤105) 个寄包柜。每个寄包柜格子数量不一,第 ii 个寄包柜有 a_i(1\le a_i\le10^5)ai​(1≤ai​≤105) 个格子,不过我们并不知道各个 a_iai​ 的值。对于每个寄包柜,格子编号从 1 开始,一直到 a_iai​。现在有 q(1 \le q\le10^5)q(1≤q≤105) 次操作:

  • 1 i j k:在第 ii 个柜子的第 jj 个格子存入物品 k(0\le k\le 10^9)k(0≤k≤109)。当 k=0k=0 时说明清空该格子。
  • 2 i j:查询第 ii 个柜子的第 jj 个格子中的物品是什么,保证查询的柜子有存过东西。

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

输入格式

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

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

输出格式

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

输入样例:

5 4

1 3 10000 118014

1 1 1 1

2 3 10000

2 1 1

输出样例:

118014

1

题解

 map容器提供一对一的查找、排序功能,因此这道题确定用map容器。

但此时需要两个数据作为钥匙才能准确查找,因此map套娃:map<int,map<int,int>>直接来做。

代码

#include <bits/stdc++.h>
using namespace std;
map<int,map<int,int>> m;  //map套map

int main(){
    long long n ,q;
    cin>>n>>q;
    for(int i1 = 0;i1<q; i1++){
        int b,i,j,k;
        cin>>b>>i>>j;
        if(b == 1){
            cin>>k;
            m[i][j] = k;
        }
        else{
            cout<<m[i][j]<<endl;
        }
    }
    return 0;
}


2.括号序列

题目

定义如下规则:

  1. 空串是「平衡括号序列」
  2. 若字符串 SS 是「平衡括号序列」,那么 \texttt{[}S\texttt][S] 和 \texttt{(}S\texttt)(S) 也都是「平衡括号序列」
  3. 若字符串 AA 和 BB 都是「平衡括号序列」,那么 ABAB(两字符串拼接起来)也是「平衡括号序列」。

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

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

而以下几个则不是:

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

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

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

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

输入格式

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

输出格式

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

输入输出样例:

输入 #1

([()

输出 #1

()[]()

输入 #2

([)

输出 #2

([])

说明/提示

数据规模与约定:对于全部的测试点,保证 ss 的长度不超过 100,且只含 ()[] 四个字符。

题解

首先遍历整个string,设置条件查找:1.合理的括号 2.不合理的括号。再遍历一遍,合理的括号直接输出,不合理的括号补全输出。

条件设置:设置一个新的整型数组,将其数值全部设成0。遍历string,当他是右括号时(即 ”)“ 和 ”]“),记录此时的下标i,并从i开始往回找。如果在i之前能找到没有被标记的、匹配的左括号(即 "(“ 和 ”[” )则两个都标记。遍历过后,标记的都是合理的,未标记的都是不合理的。

代码 

#include <bits/stdc++.h>
using namespace std;
int a[105];//设置标记的数组,此时默认数组内全是0。


int main(){
    string s;
    cin>>s;

    for(int i = 0;i<s.length();i++){
        if(s[i] == ')'){
            for(int j = i-1;j >= 0;j--){
                if(s[j] == '(' && a[j] == 0) {
                    a[i] = 1;//标记合理的右括号
                    a[j] = 1;//标记合理的左括号
                    break;
                   }
                else if (s[j] == '[' && a[j] == 0) break; 
            }
        }
        //同理
        else if(s[i] == ']'){
            for(int j = i-1;j >= 0;j--){
                if(s[j] == '['&& a[j] == 0) {
                    a[i] = 1;
                    a[j] = 1;
                    break;
                   }
                else if (s[j] == '(' && a[j] == 0) break;
            }
        }
    }

    for(int i = 0;i<s.length();i++){
        if(a[i] == 1) cout<<s[i];//合理的直接输出
        else{
            //不合理的补全输出
            if(s[i] == '(' || s[i] == ')') cout<<"()";
            else cout<<"[]";
        }
    }
    return 0;
}

3.后缀表达式

题目

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

如:\texttt{3*(5-2)+7}3*(5-2)+7 对应的后缀表达式为:\texttt{3.5.2.-*7.+@}3.5.2.-*7.+@。在该式中,@ 为表达式的结束符号。. 为操作数的结束符号。

输入格式

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

输出格式

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

输入输出样例

输入 #1

3.5.2.-*7.+@

输出 #1

16

说明/提示

数据保证,1 \leq |s| \leq 501≤∣s∣≤50,答案和计算过程中的每一个值的绝对值不超过 10^9109。

题解

一看就要用stack。

输入一个string,在这个string中,“@”是整个表达式的终止符号,“+”、“-”、“*”、“/”任意一个是stack的终止入栈的标志。因此整个过程就是:数字存入栈,遇到符号停止,并从栈顶取数字计算。继续存入数字,继续计算,直到遇到“@”。

以上就是代码运行全过程。

代码

#include <bits/stdc++.h>
using namespace std;
stack<int> st;//建立栈
int x,y;

int main(){
    string str;
    cin>>str;
    int a = 0;
    for(int i = 0; str[i] != '@' ; i++){

        if(str[i] <= '9' && str[i] >= '0'){

            a =  a * 10 + (str[i] - '0');//存入数字(很多位)

        }

        else if(str[i] == '.'){
            st.push(a);//遇到“.” 入栈
            a = 0;
        }

      else if(str[i] == '+' || str[i] == '-'||str[i] == '*'||str[i] == '/'){
        x = st.top();
        st.pop();
        y = st.top();
        st.pop();

        //取出栈顶的两位数

        if(str[i] == '+') st.push(x+y);//运算结果要重新入栈
        else if(str[i] == '-') st.push(y-x);
        else if(str[i] == '*') st.push(x*y);
        else if(str[i] == '/') st.push(y/x);

      }
    }
    cout<<st.top();
  return 0;
}

4.队列安排

题目

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

  1. 先将 11 号同学安排进队列,这时队列中只有他一个人;

  2. 2-N2−N 号同学依次入列,编号为 ii 的同学入列方式为:老师指定编号为 ii 的同学站在编号为 1\sim(i-1)1∼(i−1) 中某位同学(即之前已经入列的同学)的左边或右边;

  3. 从队列中去掉 M(M<N)M(M<N) 个同学,其他同学位置顺序不变。

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

输入格式

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

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

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

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

输出格式

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

输入输出样例

输入 #1

4
1 0
2 1
1 0
2
3
3

输出 #1

2 4 1

说明/提示

样例解释:

将同学 22 插入至同学 11 左边,此时队列为:

2 1

将同学 33 插入至同学 22 右边,此时队列为:

2 3 1

将同学 44 插入至同学 11 左边,此时队列为:

2 3 4 1

将同学 33 从队列中移出,此时队列为:

2 4 1

同学 33 已经不在队列中,忽略最后一条指令

最终队列:

2 4 1

数据范围

对于 20\%20% 的数据,有 1\leq N\leq 101≤N≤10;

对于 40\%40% 的数据,有 1\leq N\leq 10001≤N≤1000;

对于 100\%100% 的数据,有 1\leq N,M\leq1000001≤N,M≤100000。

题解

 有“插入”和“删除”,确定用链表——list。

初始有一个1号同学,在list中直接加入数字“1”。到之后读入两个数据,x号同学的左边/右边。每一次插入同学,都先遍历list,找到x的迭代器。如果在x的左边,则迭代器不变。如果在x的右边,则迭代器后退一位。完成插入同学。

删除是根据list中的数值来确定删除谁,因此调用自带的remove()函数,直接删除。(但是会超时)

插入和删除完毕,输出list。

代码

#include <bits/stdc++.h>
using namespace std;

list<int> v;
list<int>::iterator it;

void print(list<int> v){
    list<int>::iterator it2 = v.begin();
    list<int>::iterator it3 = v.end();
    it3--;

    for(;it2 != it3;it2++){
        cout << ( *it2 ) << " ";
    }
    cout<<(*it3);//最后不能有空格
}


int main(){
    int n,m;
    cin>>n;
    v.push_back(1);//初始时已经有一位同学在里面

    for(int i = 2;i<=n;i++){
        //插入
        int x,b;
        cin>>x>>b;

        for(list<int>::iterator it1 = v.begin(); it1 != v.end(); it1++){
            if((*it1) == x){  //寻找标号为x的
                if(b == 1) it1++;//b=1 为往x号的右边插入 迭代器往后移动一位
                //若要往x左边插入 迭代器不变

                v.insert(it1,i);
                break;
          }
        }
    }

    //删除
    cin>>m;
    for(int i = 0;i<m; i++){
        int x;
        cin>>x;
        v.remove(x);//STL中的list容器提供数值删除的方法函数 直接用
    }
    print(v);
  return 0;
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值