IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 题集 (简单数据结构) -> 正文阅读

[数据结构与算法]题集 (简单数据结构)

A?Sliding Window(POJ - 2823)

(单调队列)
题目链接

本题维护两个单调队列就可以了
在求窗口内最大值时,需要我们维护一个单调递减的队列,队头所对应的元素永远是最大的,只有在当前位置到队头位置长度超过窗口长度时,才将队头弹出,在维护递减性时,如果当前位置所对应元素比队尾所对应元素要大,那么弹出队尾,直到队空或者找到一个比当前位置所对应元素大的。
而求窗口最小值时反之就行

在POJ交的时候交C++,不要交G++

代码

#include <cstdio>
const int M = 1000010;
int num[M], min1[M], max1[M], que1[M], que2[M];	
int n, m;
void find_min() {
	int l = 1, r = 0, cnt = 0;
	for (int i = 1; i <= n; ++i) {
		while (l <= r && i - que1[l] + 1 > m) l++;
		while (l <= r && num[i] <= num[que1[r]]) r--;	
		que1[++r] = i;
		if (i < m) continue;
		min1[++cnt] = num[que1[l]];
	}
	for (int i = 1; i <= cnt; ++i) printf("%d ", min1[i]); printf("\n");
}
void find_max() {
	int l = 1, r = 0, cnt = 0;
	for (int i = 1; i <= n; ++i) {
		while (l <= r && i - que2[l] + 1 > m) l++;
		while (l <= r && num[i] >= num[que2[r]]) r--;
		que2[++r] = i;
		if (i < m) continue;
		max1[++cnt] = num[que2[l]];
	}
	for (int i = 1; i <= cnt; ++i) printf("%d ", max1[i]); printf("\n");
}
int main() {

	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) scanf("%d", &num[i]);
	find_min(); find_max();
	return 0;
}

B?Bad Hair Day (POJ - 3250)

(单调队列)
题目链接

本题维护一个单调递减的单调对列就可以,如果当前位置对应元素大于等于队头元素 那么弹出队头元素,直到找到第一个严格大于当前位置对应元素停下。每次队内元素长度 - 1 也就是r - l,也就是其他能看到当前新加入的牛的数量,所以每次加r - l。

#include <cstdio>
#define ll long long 
const int M = 80080;
int n;
int num[M], que[M];
void Solve() {
	int l = 1, r = 0;
	ll ans = 0;
	for (int i = 1; i <= n; ++i) {
		while (l <= r && num[i] >= num[que[r]]) r--;
		que[++r] = i;
		if (r > l) ans += r - l;
	}
	printf("%lld", ans);
}
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) scanf("%d", &num[i]);
	Solve();
	return 0;
}

C?Largest Rectangle in a Histogram (POJ - 2559)’

(单调栈)

题目链接

本题可以维护一个单调栈,每次新进入一个矩形如果高度大于栈顶,则入队,如果小于等于栈顶则证明栈顶的矩形的高度不可能超过当前要新进入的矩形也就是栈顶矩形的右边界已经确定,则已经可以开始计算栈顶矩形的高度,因为单调栈是逐渐上升的,那么左边不可能超过栈内栈顶之下的元素,所以左边界为栈内栈顶之下的元素的位置。左右边界都可以确定,那么宽度就可以确定,而高度为栈顶矩形的高度。最后每次出一个栈顶元素,求一次面积最大值。
最后要注意,求到第n + 1个元素,将n + 1个矩形高度设置为0,让栈内所有未求出的矩形面积都跑出来,避免漏掉某些高度的情况。

#include <iostream>
#include <cstdio>
#include <stack>
using namespace std;
#define ll long long 
const int M = 100010;
ll num[M];
int main() {
	int n;
	ll weight, height;
	while (scanf("%d", &n)) {
		if (n == 0) break;
		for (int i = 1; i <= n; ++i) scanf("%lld", &num[i]);
		stack<ll> sta;
		ll ans = 0;
		num[n + 1] = 0;
		for (int i = 1; i <= n + 1; ++i) {
			while (!sta.empty() && num[i] <= num[sta.top()]) {
				height = num[sta.top()]; sta.pop(); 
				if (sta.empty()) weight = i - 1;
				else weight = i - 1 - sta.top();			
				ans = max(ans, weight * height);
			}
			sta.push(i);
		}
		printf("%lld\n", ans);
	}
	return 0;
}

D?Max Sum of Max-K-sub-sequence (HDU - 3415)

(前缀和 + 单调队列)
题目链接

题意:给定长度为n的循环序列,计算最大长度不超过 k 的子序列的最大和
本题可以维护单调上升的队列,队列元素为到点 i 的前缀和, 子段和大小为 sum[i] - sum[que[l] - 1],如果后面进来的子段和比队尾的小,那么后面的点与前面的点相连而成的子段,一定不会取到队尾的点,那么就可以将队尾弹出。
最后只需要在每段子段和大于ans 时进行ans 和 ansr ansl 的改变就可以了

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int M = 100010;
const int INF = 0x3f3f3f3f;
int num[M << 1], sum[M << 1], que[M << 1];
void find_(int n, int k) {
	memset(que, 0, sizeof(que));
	int l = 1, r = 0;
	int ans = -INF, ansr, ansl;
	for (int i = 1; i <= 2 * n; ++i) {
		while (l <= r && i - que[l] + 1 > k) l++;
		while (l <= r && sum[i - 1] < sum[que[r] - 1]) r--;
		que[++r] = i;
		if (ans < sum[i] - sum[que[l] - 1]) {
			ans = sum[i] - sum[que[l] - 1];
			ansr = i;
			ansl = que[l];
		}
	}
	if (ansr > n) ansr -= n;
	printf("%d %d %d\n", ans, ansl, ansr);
}
int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		int n, k;
		scanf("%d%d", &n, &k);
		for (int i = 1; i <= n; ++i) {
			scanf("%d", &num[i]);
			num[i + n] = num[i];
		}
		for (int i = 1; i <= 2 * n; ++i) sum[i] = sum[i - 1] + num[i];
		find_(n, k);
	}
	return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-10-26 12:25:59  更:2021-10-26 12:27:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:34:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码