hdu 5818 Joint Stacks 2016 Multi-University 7

2023-11-10

Problemacm.hdu.edu.cn/showproblem.php?pid=5818

官方题解bestcoder.hdu.edu.cn/blog/2016-multi-university-training-contest-7-solutions-by-sysu/

题意:两个栈,支持push、pop、merge 3种操作

push x y :把 y 压入栈 x

pop x :栈 x 弹出一个元素,输出它的值

merge x y :把 y 中的元素全部移到 x 中,并且保持所有元素的进栈时的先后顺序

分析:官方题解中有种解法,是开第3个栈,当要合并的时候把两个栈里的元素全部放到这个栈里,并且清空原来两个栈

我理解:

#include <stdio.h>
#define N 100000
struct
{
	int v;
	int id; // 标明元素的进栈先后
} a[N], b[N], c[N]; // 3个栈
int main()
{
	int n,kase=1;
	while( ~scanf("%d%*c",&n) && n )
	{
		printf("Case #%d:\n",kase++);
		// 3个栈的栈顶指针
		int topa = 0, topb = 0, topc = 0;
		// “时间”标明元素进栈先后
		int time;
		// own标记c中的元素属于A还是B
		char own = '\0';
		for(time=0; time<n; time++)
		{
			char op[7],who;
			int val,i,j;
			scanf("%s %c%*c",op, &who);
			if( op[1] == 'u' ) // push
			{
				scanf("%d%*c", &val);
				if( who == 'A' )
				{
					a[topa].v = val;
					a[topa++].id = time;
				}
				else
				{
					b[topb].v = val;
					b[topb++].id = time;
				}
			}
			else if( op[1] == 'o' ) // pop
			{
				if( who == 'A' )
				{
					if( topa ) // 如果a栈中有元素,必是最新的
						printf("%d\n", a[--topa].v);
					else if( topc && own == 'A' ) // c中有元素且属于A
						printf("%d\n", c[--topc].v);
				}
				else
				{
					if( topb )
						printf("%d\n", b[--topb].v);
					else if( topc && own == 'B' )
						printf("%d\n", c[--topc].v);
				}
			}
			else // merge
			{
				// 读掉第2个参数
				scanf("%*s");
				// 把a、b栈的元素都放进c栈
				for(i=j=0; i<topa || j<topb; )
				  if( i<topa && j<topb ) //a、b栈都非空
				  {
					  if( a[i].id < b[j].id ) // 比较入栈顺序
					  {
						  c[topc].v = a[i].v;
						  c[topc++].id = a[i++].id;
					  }
					  else
					  {
						  c[topc].v = b[j].v;
						  c[topc++].id = b[j++].id;
					  }
				  }
				  else if( i<topa ) // a栈非空
				  {
					  c[topc].v = a[i].v;
					  c[topc++].id = a[i++].id;
				  }
				  else // b栈非空
				  {
				      c[topc].v = b[j].v;
				      c[topc++].id = b[j++].id;
				  }
				// 清空a、b栈
				topa = topb = 0;
				// 第1个参数表示归属
				own = who;
			}
		}
	}
	return 0;
}
可以开两个栈,记录两个栈的栈顶指针(topa,topb)和各自的一个标记指针(marka,markb)

要合并时,比如 merge A B,就把 b 栈的标记指针打到 a 栈的栈顶指针那,表示此标记开始以下的元素都属于 b 栈

同时把 a 栈在 b 栈上的标记指针打到 b 栈的栈底

那么属于 a 栈的元素就包括:a 栈中从栈顶指针 topa 到 b 的标记指针 markb 中间一段的元素,和 b 栈中从 a 栈的标记指针 marka 到 b 栈栈底一段的元素

要弹栈时,比如 pop B,就要比较 topb 所指元素(如果有)与 markb 所指元素(如果有)的进栈顺序,输出较新的一个,并且删掉那个元素

用双向链表实现栈(因为删元素的时候要把与它相邻的两个元素连起来)

注意:如果 pop B 的时候要删的是 markb 所指的元素,而 topa == markb,那么在删元素前更改 markb 的指向时,要把 topa 也一同改了(不然 topa 成野指针)

#include <stdio.h>
#include <stdlib.h>

typedef struct Node
{
	int v,id;
	struct Node *pre,*next; // 上面和下面
}node;

void push(node **s, int val, int tm)
{
	node *p = malloc( sizeof( node ) );
	p->v = val;
	p->id = tm;
	p->pre = NULL;
	p->next = *s;
	if(*s)
	  (*s)->pre = p;
	*s = p;
}
/* 删除元素 */
void erase(node **me, node **histop)
{
	node *q = *me;
	printf("%d\n", q->v);
	if( q->pre )
		q->pre->next = q->next;
	if( q->next )
		q->next->pre = q->pre;
	*me = q->next;
	if( *histop == q )
		*histop = *me;
	free(q);
}

void pop(node **mytop, node **mymark, node **histop, node *hismark)
{
	// 我栈中有属于我的元素,他栈中没有
	if( *mytop != hismark && !*mymark )
		erase(mytop,histop);
	// 我栈没有,他栈有
	else if( *mytop == hismark && *mymark )
		erase(mymark,histop);
	// 我有他有
	else if( *mytop != hismark && *mymark )
		if( (*mytop)->id < (*mymark)->id )
			erase(mymark,histop);
		else
			erase(mytop,histop);
}

void merge(node **mymark, node **hismark, node *histop)
{
	// 标记打到对方栈顶
	*mymark = histop;
	// 对方的标记打到“栈底”
	*hismark = NULL;
}
/* 销毁链表 */
void destroy(node *s)
{
	while(s)
	{
		node *q = s;
		s = s->next;
		free(q);
	}
}

int main()
{
	int n,kase=1;
	while( ~scanf("%d%*c",&n) && n )
	{
		int i;
		// 栈顶指针,标记指针
		node *topa,*topb,*marka,*markb;
		printf("Case #%d:\n", kase++);
		topa = topb = marka = markb = NULL;
		for(i=0; i<n; i++)
		{
			char op[7],who;
			int val;
			scanf("%s %c%*c", op, &who);
			if( op[1] == 'u' )
			{
				scanf("%d%*c", &val);
				if( who == 'A' )
					push(&topa, val, i);
				else
					push(&topb, val, i);
			}
			else if( op[1] == 'o' )
			{
				if( who == 'A' )
					pop(&topa, &marka, &topb, markb);
				else
					pop(&topb, &markb, &topa, marka);
			}
			else
			{
				scanf("%*s");
				if( who == 'A' )
					merge(&marka, &markb, topb);
				else
					merge(&markb, &marka, topa);
			}
		}
		// 销毁链表
		destroy(topa);
		destroy(topb);
	}
	return 0;
}
本来想用C++的 vertor 来写栈,删元素时直接用它的 erase(),然而wa了…不知道它删完一个元素后,是不是后面元素的下标都自动 -1 还是怎么变,还是因为写漏了个冒号…

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

hdu 5818 Joint Stacks 2016 Multi-University 7 的相关文章

  • SL4 AutoCompleteBox 重复筛选结果问题

    我在 AutoCompleteBox 过滤方面遇到问题 它似乎记住了之前的过滤器 例如 我输入 A 它会返回 1 项 我删除 A 并输入 Z 这应该返回 1 项 问题是它返回 A 过滤器加上 Z 的结果 我删除 Z 并输入 S 这会带回 2
  • DispatcherTimer 未按时执行

    我正在使用 c 中的 DispatchTimer 编写一个时钟应用程序 但由于某些原因 我的时钟似乎时不时地跳过 1 秒 例如 52 秒 gt 54 秒 跳过 53 秒 在我看来 计时器并不是每秒都执行一次 DispatcherTimer
  • MVC 重定向到没有控制器的视图

    希望应该是一个简单的 我创建了一个通用错误视图 当整个站点的操作方法内发生异常时 我想显示该视图 我创建了一个部分页面 所有导航都位于其中 因此我不需要在此视图上使用控制器 那么如何从控制器内的操作方法重定向到它 像这样的东西 HttpPo
  • WebClient读取错误页面的内容

    我有一个加载页面内容的应用程序 我使用 WebClient 类 即使服务器返回 404 500 等错误 我也需要检索内容 我需要这样的东西 WebClient wc new WebClient string pageContent try
  • C# 中的协变和逆变

    首先我要说的是 我是一名正在学习 C 编程的 Java 开发人员 因此 我会将我所知道的与我正在学习的进行比较 我已经使用 C 泛型几个小时了 我已经能够在 C 中重现我在 Java 中知道的相同内容 除了几个使用协变和逆变的示例 我正在读
  • 关闭 XDOCUMENT 的实例

    我收到这个错误 该进程无法访问文件 C test Person xml 因为它是 被另一个进程使用 IOException 未处理 保存文件内容后如何关闭 xml 文件的实例 using System using System Collec
  • 如何在 Windows 窗体中运行屏幕保护程序作为其背景?

    如何在 Windows 窗体中运行屏幕保护程序作为其背景 用户还可以在屏幕保护程序运行时与表单控件进行交互 为什么这个 我们有一个案例 需要在用户时运行 Windows Bubbles 屏幕保护程序 可以继续与表单控件交互吗 您可以使用以下
  • 将 C# 反射代码移植到 Metro-Ui

    我正在尝试移植使用反射的现有 C 类 通用工厂 但我无法编译这段代码 Type types Assembly GetAssembly typeof TProduct GetTypes foreach Type type in types i
  • C 中的模仿函数重写

    具体来说 函数重写能够调用基本重写方法 这有两部分 一个是预编译的库代码 1 另一个是库的用户代码 2 我在这里实现了一个尽可能最小的经典 Person 和 Employee 示例 非常感谢了解 OOP 概念的铁杆 C 开发人员的回应 我正
  • 用 C# 制作 Vista 风格的应用程序

    我正在运行 Windows Vista 并且希望外观看起来像常规 Vista 程序 有没有关于如何构建 Vista 风格应用程序的真正好的教程 文章 我还想学习如何使用本机代码并将其转换为 C 如this http bartdesmet n
  • 抽象类或接口。哪种方式是正确的?

    有两种方法可以选择抽象类或接口 微软解决方案和Oracle解决方案 微软 设计指南 请使用抽象 在 Visual Basic 中为 MustInherit 类而不是接口来将协定与实现分离 http msdn microsoft com en
  • 不要声明只读可变引用类型 - 为什么不呢?

    我一直在阅读这个问题 https stackoverflow com questions 2274412 immutable readonly reference types fxcop violation do not declare r
  • 是什么原因导致 Linq 错误:此方法无法转换为存储表达式?

    我有一堆具有相同 select 语句的 Linq to Entity 方法 所以我想我会很聪明 并将其分离到它自己的方法中以减少冗余 但是当我尝试运行代码时 我得到了以下内容错误 该方法不能转化为 商店表达式 这是我创建的方法 public
  • realloc():重新分配为 char * 上的 strcat 腾出空间时下一个大小无效 [重复]

    这个问题在这里已经有答案了 我在以下代码中收到无效内存错误 printf s n FINE 5 printf s LENGTH IS d n FINE 6 strlen buffer char realloc buffer strlen b
  • C++ 标准中短语“构造函数没有名称”的含义

    在尝试理解 C 标准中的 构造函数没有名称 这句话时 我似乎在 clang 中发现了一个错误 有人可以证实这一点吗 VS2015 and gcc rejects this code and I think they it are is co
  • 为什么C语言中可以使用多个分号?

    在 C 中我可以执行以下操作 int main printf HELLO WORLD 它有效 这是为什么 我个人的想法 分号是一个 NO OPERATION 来自维基百科 指示符 拥有一大串分号与拥有一个分号并告诉 C 语句已结束具有相同的
  • 将一个 long 转换为两个 int 以进行重构

    我需要将一个参数作为两个 int 参数传递给 Telerik Report 因为它不能接受长参数 将 long 拆分为两个 int 并在不丢失数据的情况下重建它的最简单方法是什么 使用掩蔽和移位是最好的选择 根据文档 long 保证为 64
  • 程序退出后,TcpListener Socket 仍处于活动状态

    当我的程序退出时 我试图停止 TCP 侦听器 我不关心套接字或任何活动客户端套接字上当前活动的任何数据 套接字清理代码本质上是 try myServer Server Shutdown SocketShutdown Both catch E
  • 创建带有部分的选项卡式侧边栏 WPF

    我正在尝试创建一个带有部分的选项卡式侧边栏 如 WPF 中的以下内容 我考虑过几种方法 但是有没有更简单 更优雅的方法呢 方法一 列表框 Using a ListBox并将 SelectedItem 绑定到右侧内容控件所绑定的值 为了区分标
  • 如何确定给定方法可以抛出哪些异常?

    我的问题和这个真的一样 找出 C 中方法可能抛出的异常 https stackoverflow com questions 264747 finding out what exceptions a method might throw in

随机推荐

  • find grep 寻找文件字符

    如果你只想在 r 类型的文件中寻找特定字符串 可以使用以下命令 grep ri universal include r i 忽略大小写 r递归所有文件 如果你只想查找文件名包含 universal 且扩展名为 r 的文件 而不是文件内容 则
  • torch.cuda.is_available()为false的解决办法

    一 问题 在进行torch进行开发的过程中 我们习惯性的会使用pip install torch这样的方式来安装torch的包 其实这样的是安装CPU的torch 在导入包 执行下面代码的过程中 会出现结果为false import tor
  • win10通过conda安装pytorch gpu

    1 安装anaconda 到官网下载最新版的anaconda 下载对应的windows版本 地址 anaconda官网 下载后直接安装 安装完成后配置环境变量 具体可以百度anaconda安装说明 安装完成后 打开cmd 输入conda v
  • Nginx HTTPS实践

    Nginx HTTPS实践 文章目录 Nginx HTTPS实践 1 HTTPS基本概述 1 1 为何需要HTTPS 1 2 什么是HTTPS 1 3 TLS如何实现加密 2 HTTPS实现原理 2 1 加密模型 对称加密 2 2 加密模型
  • 用matlab编程实现对图像的均值滤波,中值滤波和拉普拉斯算子锐化

    1 均值滤波 均值滤波 用包含在滤波掩模邻域内的像素的平均灰度值去代替每个像素点的值 用途 用于模糊处理和减少噪声 盒滤波器 加权平均滤波器 均值滤波 clc close all clear all I rgb2gray imread fi
  • java编程练习

    package HomeWork05 import java util Scanner public class HomeWork05 public static void main String args Scanner sc new S
  • PAMI19 - 强大的级联RCNN架构《Cascade R-CNN: High Quality Object Detection and Instance Segmentation》

    文章目录 原文 初识 相知 Challenge to High Quality Detection Cascade RCNN 与相似工作的异同 扩展到实例分割 回顾 参考 原文 https arxiv org pdf 1906 09756
  • springboot框架中使用websocket传输内容过长的问题解决

    很多业务中使用websocket进行前后台的长连接 一般情况下用作及时性消息推送等 而一旦传输内容过长 例如传输一些图片音频的base64编码之类的 很容易出现过长问题 甚至不提示问题直接截断乃至丢失数据 解决方法如下 很多人网上查阅方法会
  • 【算法 -- LeetCode】(026)删除有序数组中的重复项

    1 题目 给你一个 升序排列 的数组 nums 请你 原地 删除重复出现的元素 使每个元素 只出现一次 返回删除后数组的新长度 元素的 相对顺序 应该保持 一致 然后返回 nums 中唯一元素的个数 考虑 nums 的唯一元素的数量为 k
  • CORDIC算法详解及FPGA实现

    CORDIC算法详解 1 平面坐标系旋转 CORDIC算法的思想是通过迭代的方法 使得累计旋转过的角度的和无限接近目标角度 它是一种数值计算逼近的方法 运算只有移位和加减 通过圆坐标系可以了解CORDIC算法的基本思想 如图1所示 初始向量
  • 线边仓

    SAP线边库管理 是又叫WIP仓 或叫线上仓 举例来说 一卷线材 总长303米 工单需用100米 于是发料发出303米 也就是一卷 其中100米上生产线 另外203米进入这个WIP仓 下次领料直接从WIP仓发出去 管控非常到位 具体操作就要
  • 11月20日 作业3 生命药剂,角色蓝图修改

    具体太麻烦了 我直接贴代码了 SPowerUp Actor h Fill out your copyright notice in the Description page of Project Settings pragma once i
  • 录屏没有声音?录制声音,3招教你搞定

    在录制屏幕内容时 声音是不可或缺的要素之一 可以有效地增强录制视频的表现力和传达效果 然而 有时候可能会遇到录屏没有声音的情况 这可能会让录制的视频失去一部分重要信息 本文将为您介绍录屏录声音的3种方法 帮助您解决录屏没有声音的问题 实现高
  • esp和ebp详解

    我的理解 国外一个比较好的汇编网站 http www tenouk com Bufferoverflowc Bufferoverflow1b html http blog sina com cn s blog c3bab4650101ogf
  • Python游戏开发入门3 Pygame屏幕绘制机制

    目录 屏幕控制 幕控制需求 幕控制的重要函数 幕模式函数 幕设置为大小可调 幕设置为全屏 幕信息函数 小游戏 伸缩型 屏幕控制 幕控制需求 幕控制的重要函数 幕模式函数 pygame display set mode r 0 0 flags
  • 【Python】bokeh画图工具库

    bokeh是python中一款基于网页的画图工具库 画出的图像以html格式保存 https blog csdn net tankloverainbow article details 80442289
  • java web期末复习_JAVAWEB期末复习题库

    JAVAWEB期末复习题库 javaweb期末复习题库 jsp Servlet 1 当访问一个Servlet时 以下Servlet中的哪个方法先被执行 D A destroy B doGet C service D init0 2 假设在m
  • [rt-thread nano] 添加串口rt-printf打印

    硬件 gd32f303 宏定义 定义宏定义 define RT USING CONSOLE define RT USING DEVICE define RT CONSOLE DEVICE NAME uart1 输出 ifdef RT USI
  • MySQL链接错误

    com mysql jdbc exceptions jdbc4 CommunicationsException Communications link failure package com spark import java sql Co
  • hdu 5818 Joint Stacks 2016 Multi-University 7

    Problem acm hdu edu cn showproblem php pid 5818 官方题解 bestcoder hdu edu cn blog 2016 multi university training contest 7