NEUQ-ACM week3线性表

【深基15.例2】寄包柜

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

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

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

输入格式

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

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

输出格式

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

输入输出样例

输入 #1

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

输出 #1

118014
1

 本题由于数据较大,使用二维数组必然造成内存溢出,为了节约内存,这里使用链表

#include<iostream>
using namespace std;
long long n,i,j,k,q,num=1;
const int maxn=1e5+5;
int main()
{
	struct save_container//该结构体用于存储物品相关信息
	{
		int i;//i号柜子
		int j;//第j个格子
		int value;//存储的内容
		int r;//l和r分别为该数据左/右侧内容
		int l;
	}s[maxn]={0,0,0,0,0};
	cin>>n>>q;//输入
	for(int y=1;y<=q;y++)
	{
		cin>>n;
		if(n-1)//n为2时,进行查询操作
		{
			cin>>i>>j;
			for(int u=s[0].r;u;u=s[u].r)
			{
				if((s[u].i==i)&&(s[u].j==j))
				{
					cout<<s[u].value<<endl;
					break;
				}
			}
		}
		else//n为1时,进行存储
		{
			cin>>i>>j>>k;
			if(!k)//k为0时删除
			{
				for(int u=s[0].r;u;u=s[u].r)//寻找目标
				{
					if((s[u].i==i)&&(s[u].j==j))
					{
						s[s[u].l].r=s[u].r;//删除
						s[s[u].r].l=s[u].l;
						s[u].r=s[u].l=0;
						break;
					}
				}
			}
			else//k不为0时将数据插入链表右端
			{
				s[num].i=i;
				s[num].j=j;
				s[num].value=k;
				s[num].r=num+1;
				s[s[num].l].r=num;
				s[s[num].r].l=num;
				num++;
			}	
		}
	}
	return 0;
}

P1241 括号序列

题目描述

定义如下规则:

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

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

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

而以下几个则不是:

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

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

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

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

输入格式

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

输出格式

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

输入输出样例

输入 #1复制

([()

输出 #1复制

()[]()

输入 #2复制

([)

输出 #2复制

()[]()

说明/提示

数据规模与约定

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

#include<iostream>
using namespace std;
int top=0,i=0;
struct kuohao
{
	char a;
	int i;
}c[1111]={'0',0},C[1111];//结构体数组c(小写)用于记录所有的括号数据(a记录括号种类,i记录是否配对)。结构体数组C(大写)用于记录所有的左括号数据(a记录括号种类,i记录该括号次序)。
int main()
{
	while(cin>>c[i].a)//输入括号
	{
		if((c[i].a=='(')||(c[i].a=='['))//将左括号存入栈C中
		{
			C[top].a=c[i].a;
			C[top].i=i;
			top++;//栈顶加一
		}
		else
		{
			if(((c[i].a==')')&&(C[top-1].a=='('))||((c[i].a==']')&&(C[top-1].a=='[')))
			{
				c[i].i=1;
				c[C[top-1].i].i=1;//当右括号与栈C顶部括号匹配时,将配对的两个括号标记为已配对(对应i改为1)
				top--;//栈顶减一
			}
		}
	i++;
	}
	for(int j=0;j<=i;j++)//输出
	{
		if(c[j].i==1)
		{
			cout<<c[j].a;//i为1时表示已配对,直接输出
		}
		else
		{
			if((c[j].a=='[')||(c[j].a==']'))//未配对的补齐后输出
			{
				cout<<"[]";
			}
			else if((c[j].a=='(')||(c[j].a==')'))
			{
				cout<<"()";
			}
		}
	}
	return 0;
}

P1449 后缀表达式 

题目描述

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

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

输入格式

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

输出格式

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

输入输出样例

输入 #1

3.5.2.-*7.+@

输出 #1

16

说明/提示

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

#include<iostream>
#include<string>
#include<cmath>
using namespace std;
const long long maxn=1e5+5;
string t="0";
char ch;
long long sta[maxn],top;//用栈存储数字,每次计算时使用顶部的两个数字
long long num(string a)//该函数用于将字符串类型数字转化为lonng long类型的数字
{
	int ans=0;
	for(int i=0;i<a.size();i++)
	{
		ans+=((int)a[i]-(int)'0')*pow(10,a.size()-1-i);
	}
	return ans;
}
int main()
{
	while(cin>>ch)
	{
		if(ch<=(int)'9'&&ch>=(int)'0')
		{
			if(t=="0")
			{
				t[0]=ch;
			}
			else
			{
				t=t+ch; 
			}
		}
		else if(ch=='.')
		{
			sta[top]=num(t);
			top++;
			t="0";
		}
		else if(ch=='@')//结束
		{
			cout<<sta[0];
			break;
		}
		else//计算
		{
			top--;
			if(ch=='+')
			{
				sta[top-1]+=sta[top];
			}
			else if(ch=='-')
			{
				sta[top-1]-=sta[top];
			}
			else if(ch=='*')
			{
				sta[top-1]*=sta[top];
			}
			else if(ch=='/')
			{
				sta[top-1]/=sta[top];
			}
		}
	}
	return 0;
}

 P1160 队列安排

 

题目描述

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

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

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

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

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

输入格式

第 11 行为一个正整数 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

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。

#include<iostream>
using namespace std;
int N,nn,k,p,n=1;
struct stu_quene//创建双向链表,a用于标记学生是否被移除
{
	int l;
	int r;
	int a;
}stu[100005]={0,0,0};
int main()
{
	stu[0].l=1;
	stu[0].r=1;
	stu[1].r=0;//首先将第一个学生插入链表,一号学生和0号学生“面对面手挽手”
	stu[1].l=0;//0号学生事实上不存在,用于判断链表的结束
	cin>>N;
	for(int i=2;i<=N;i++)
	{
		cin>>k>>p;
		n++;
		if(p)//插入左边
		{
			stu[n].l=k;
			stu[n].r=stu[k].r;
			stu[stu[k].r].l=n;
			stu[k].r=n;
		}
		else//插入右边
		{
			stu[n].r=k;
			stu[n].l=stu[k].l;
			stu[stu[k].l].r=n;
			stu[k].l=n;
		}
	}
	cin>>nn;//输入需要移除学生的数量
	for(int i=1;i<=nn;i++)
	{
		cin>>k;
		stu[k].a=1;//将被移除学生的a标记为1
	}
	for(int i=stu[0].r;i;i=stu[i].r)//从0号学生开始,向右遍历链表,回到0号时结束
	{
		if(stu[i].a)
		{
			continue;
		}
		cout<<i<<" ";
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值