做题随笔:P10465

Solution

题意

原题链接

给定数列 \(a_N\),按以下要求分为 \(n\) 组:

  1. 每组中的数单调不降。
  2. 每组中的数在原数列中的下标单调递减/单调递增/先递减再递增。(思考一下双向队列插入值的过程显然有:越往两端的越后入队)
  3. 存在一种方法,使所有分组拼接后整体单调不降。

求最小的 \(n\)

分析

题目要求最终序列不降,所以断不可以按照输入顺序处理(所以 Sherry 才觉得棘手呢)。为什么呢?考虑一下样例:

3 6 0 9 6 3

如果直接按照输入顺序接,显然可以有分组方法: \([0,3,6,9],[3,6]\),不满足要求 \(3\)。其实就是在不知道所有数的情况下,可能把 \(l,r,mid(l < mid < r)\)\(l,r\)\(mid\) 分在了两组,导致无解。

为了避免无解的情况,一个很明显的策略是把所有数读入不降序排序后再处理,于是要求 \(1\)\(3\) 容易满足,接下来问题就在要求 \(2\):为了满足下标的要求,在排序时记录下标,按排序后的顺序逐位验证要求 \(2\),不满足则 \(n\gets n+1\) 即可,数据处理流程如下:

3 6 0 9 6 3\\初始数据
0 3 3 6 6 9\\排序后
3 1 6 2 5 4\\下标,验证此数组计数

还需注意两个小问题:

  1. 初始按照什么单调性来?

    一个完整的队列应是先递增再递减的,所以初始状态应为递减。

  2. 相等的数怎么处理?

    相等的数是完全初下标外等价的,相当于可以任意交换,而且一定要放在一组(不然无解或可能不是最小),故相等的数下标自身须有序,即相等的数放在一起,排序后考虑。而内部有序,其实最终只需考虑端点值即可。

3 [1 6] [2 5] 4\\相等的数一起考虑

实现

全部读入,记录下标后升序排序,全部扫一遍,相等的放一起记录端点值,转化为拼接区间。变量记录当前单调性,拼接时:还满足则继续,不满足则反转单调性,当转为递减时队列数增加一。

Code

#include <iostream>
#include <cstdio>
#include <cctype>
#include <algorithm>

using namespace std;

typedef long long ll;

inline ll fr() {
	ll x=0,f=1;char c=getchar();
	while(!isdigit(c)) {
		if(c=='-') f=-1;
		c=getchar();
	}
	while(isdigit(c)) {
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

const int maxn=2e5+1000;

struct node {
	ll x,tag;
}num[maxn];
struct intva{
	ll l=1145141919,r=-1145141919;//这个初始值还没炸过(笑)
}qu[maxn];
ll n,ans=1;
bool down=true;

inline bool cmp1(node n1,node n2) {return n1.x<n2.x;}

int main() {
	n=fr();
	for(register int i = 1; i <= n; i++) {num[i].x=fr();num[i].tag=i;}
	sort(num+1,num+1+n,cmp1);
	ll now=num[1].x,cnt=1;//记得初始化
	qu[1].l=num[1].tag;qu[1].r=num[1].tag;
	for(register int i = 2; i <= n; i++) {
		if(num[i].x!=now) {
			now=num[i].x;
			cnt++;
			i--;//就是换一个区间重新来
		}
		else {
			qu[cnt].l=min(qu[cnt].l,num[i].tag);
			qu[cnt].r=max(qu[cnt].r,num[i].tag);
		}
	}
	for(register int i = 2; i<= cnt; i++) {
		if(down) {
			if(qu[i-1].l<qu[i].r) {
				down=false;
			}
		}
		else {
			if(qu[i-1].r>qu[i].l) {
				down=true;
				ans++;
			}
		}
	}
	printf("%lld\n",ans);
	return 0;
}

后话

感觉有用,还请点个赞吧!

posted @   Tenil  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示