WEEK3 链表,map,和vector

本周通过题单上的四道题基本了解了vector ,map的用法

并利用其进行二维映射和构建链表(单向,双向)

vector  用法:

vector <char> v; // vector默认长度是0, 类型可以是c++的标准类型,也可以是自己定义的类或结构体
vector <int> v(N); // 效果类似int v[N];但是N可以是变量
vector <int> v(N, i); // 可变数组最开始有N个元素,每个元素的值是i,i可以省略不写
 

 注意 

vector <int> v(N); 
vector <int> v(N, i);

在结构体中不可声明(在编译过程中无法执行)

只能在程序执行时运行。

题目描述

超市里有 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 个整数,表示一次操作。

输出格式

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

输入输出样例

输入 #1复制

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

输出 #1复制

118014
1

基本思路 :

首先我尝试用vector

建立结构体


struct guizi
{
vector<string> wupin;
vector<int> next;
	int xuhao=0;
	
	
};
struct chaoshi
{
	vector <guizi> gui;
	
};

 并利用vector的resize和push_back

具体代码如下:

#include <bits/stdc++.h>

using namespace std;
struct guizi
{
vector<string> wupin;
vector<int> next;
	int xuhao=0;
	
	
};
struct chaoshi
{
	vector <guizi> gui;
	
};
chaoshi chao;

void hanshu2(int temp1,int temp2,string temp3)

{   
chao.gui[temp1].xuhao++;
chao.gui[temp1].wupin.push_back(temp3);
chao.gui[temp1].next.push_back(temp2);

return;
 

	
	
}

void hanshu1(int temp1,int temp2 )
{
	
		for(int i=chao.gui[temp1].xuhao-1;i>=0;i--)
		{
			if(chao.gui[temp1].next[i]==temp2)
			{
			cout<<chao.gui[temp1].wupin[i]<<endl;break;}
		}
	
	return;
	
}
int main()
{   int n,q,temp1,temp2,flag;
string temp3;
  cin>>n>>q;

	chao.gui.resize(n+1);

	for(int i=0;i<q;i++)
	{ cin>>flag;
	  if(flag==2)
	  {
	  	cin>>temp1>>temp2;
	  	hanshu1(temp1,temp2);
	  }
	  else
	  {
	  	cin>>temp1>>temp2>>temp3;
	  	hanshu2(temp1,temp2,temp3);
	  }
	}
	
}

	

但是这种方法在查询第 ii 个柜子的第 jj 个格子中的物品是什么的时候

时间复杂度是O(n)

在最后一个测试点是会超时

因此使用map进行hash映射

map用法:

自动建立key - value的对应。

map<数据类型key, 数据类型value> 映射名称personal;

基本操作:插入


 
第一种 用insert函數插入pair
mapStudent.insert(pair<int, string>(000, "student_zero"));
 
第二种 用insert函数插入value_type数据
mapStudent.insert(map<int, string>::value_type(001, "student_one"));
 

第三种 mapStudent[123] = "student_first";
mapStudent[456] = "student_second";

关键:

第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的 插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是不能在插入数据的,但是用数组方式就不同了,它可以覆盖以前该关键字对 应的值。

     begin()         返回指向map头部的迭代器

     clear()        删除所有元素

     count()         返回指定元素出现的次数(1或0)

     empty()         如果map为空则返回true

      end()           返回指向map末尾的迭代器

      erase()         删除一个元素

      find()          查找一个元素

       get_allocator() 返回map的配置器

      insert()        插入元素

   upper_bound()    返回键值>给定元素的第一个位置

     lower_bound()   返回键值>=给定元素的第一个位

     rend()          返回一个指向map头部的逆向迭代器

     size()          返回map中元素的个数

     swap()           交换两个map

     value_comp()     返回比较元素value的函数

AC代码如下;‘

#include<bits/stdc++.h>
using namespace std;
map <int,map<int,string>>yingshe;
int main(){
	int n,q,x,y,k;
	string z;
    cin>>n>>q;
    for(int i=1;i<=q;++i){
        scanf("%d%d%d",&k,&x,&y);
        if(k==1){
            cin>>z;
            yingshe[x][y]=z;//将z赋值给key为x(柜子号)y(格子号)
        }
        else{
            cout<<yingshe[x][y]<<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,且只含 ()[] 四个字符。

思路 


struct XIN
{
	int flag;
	char zifu;
};

创建结构体XIN

flag用来判断是否配对完成

#include <bits/stdc++.h>

using namespace std;
struct XIN
{
	int flag;
	char zifu;
};
vector<XIN> xin;

void hanshu(int temp)
{  
	for(int k=temp;k>=0;k--)
	         {  
	         	if(xin[k].flag==1)
	         	{
	         		if((xin[k].zifu=='('&&xin[temp].zifu==')')||(xin[k].zifu=='['&&xin[temp].zifu==']'))
                      {
                      	xin[k].flag=0;
	       	     xin[temp].flag=0;return;
					  }
					  else return;
				 }
	
}
}


int main()
{
	string s;
	cin>>s;
	
	int len=s.length(),temp;
	xin.resize(len);
	for(int i=0;i<len;i++)
	{
	 xin[i].zifu=s[i];
	 if(s[i]=='['||s[i]=='(')
	 xin[i].flag=1;
	 else {
	       xin[i].flag=2;temp=i;
	       hanshu(temp);
	       
	       
	       	     
		     
	 
	     }
	    
	    
	    
	}
	

	for(int i=0;i<len;i++)
	{
		if((xin[i].flag==1&&xin[i].zifu=='(')||(xin[i].flag==2&&xin[i].zifu==')'))
		cout<<"()";
	else	if((xin[i].flag==1&&xin[i].zifu=='[')||(xin[i].flag==2&&xin[i].zifu==']'))
		cout<<"[]";
		else cout<<xin[i].zifu;
	
	}
	
}

 输入 到string中

从string【0】开始遍历

根据题目要求观察是否配对

若配对 则将其flag化为0

最后再次遍历,若flag不为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。

AC代码

​
#include <bits/stdc++.h>
using namespace std;
struct ZHAN 
{
long long	int data[50];
	int top;
};
int main()
{   int now,ans=0;
	char ch;
	ZHAN zhan;
	zhan.top=0;
	while((ch=getchar())!='@')//限制输入格式
	{
		 if(ch>='0'&&ch<='9') now*=10,now+=ch-'0';//将字符形式转化为数字
    else if(ch=='.'){
                       zhan.top ++;
                       zhan.data[zhan.top]=now;
                       now=0;
                     }
     else if(ch=='-')  {
	                    zhan.data[zhan.top-1]=zhan.data[zhan.top-1]-zhan.data[zhan.top];zhan.top=zhan.top-1;}
 else if(ch=='+')  {
	                    zhan.data[zhan.top-1]=zhan.data[zhan.top-1]+zhan.data[zhan.top];zhan.top=zhan.top-1;}
	                    
	                     else if(ch=='*')  {
	                    zhan.data[zhan.top-1]=zhan.data[zhan.top-1]*zhan.data[zhan.top];zhan.top=zhan.top-1;}
	                    
	                     else if(ch=='/')  {
	                    zhan.data[zhan.top-1]=zhan.data[zhan.top-1]/zhan.data[zhan.top];zhan.top=zhan.top-1;}
	                    
	                                      
	}//加减乘除四种运算
	cout<<zhan.data[1];
}

​

用结构体实现入栈出栈

将char转换为数字。

题目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。

思路

利用三个数组

实现双向链表

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int mx=1e5+10;
int n,m;
struct T{
    int l,r;        //每个同学的“左右手” 
    int d;          //表示同学是否输出 
}t[mx]={0};
void add(int i,int k,int f)       //新增同学 
{
    if(f==1)         //左 
    {
        t[k].r=t[i].r;
        t[k].l=i; 
        t[i].r=k;
        t[t[k].r].l=k;
    }
    else             //右 
    {
        t[k].r=i;
        t[k].l=t[i].l;
        t[i].l=k;
        t[t[k].l].r=k;
    }
}
int main()
{
    int x,k,f;
    cin>>n;
    t[0].r=0,t[0].l=0;
    add(0,1,1);
    for (int i=2;i<=n;i++)
    {
        cin>>x>>f;
        add(x,i,f);
    }
    cin>>m;
    while(m--)
    {
        cin>>x;
        t[x].d=1;         //将该同学标记为不输出 
    }
    for (int i=t[0].r;i;i=t[i].r)
    {
        if (t[i].d==0)    //输出未标记的 
          cout<<i<<" ";
    }
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值