坑点:数组个数和数组值域相同,去重后个数n改变前,用N存值域

本文介绍了如何使用C++编程语言解决一个问题,给定一个数组,其中包含一段段连续相同的数,找到这些连续子数组中的后缀最小值,当遇到重复次数大于1的数时,将该子数组变为0。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
#define pb push_back
#define lson p << 1
#define rson p << 1 | 1
#define fi first
#define se second
const int maxn = 1e6 + 5, maxm = 5e3 + 5;
int a[maxn], b[maxn];
int n, m;
string s;
bool vis[maxn];
int l[maxn], r[maxn], cnt[maxn];

void solve()
{
	int k;
	cin >> n;
	for(int i = 1; i <= n; i++){
		vis[i] = 0;
		r[i] = 0;
		cnt[i] = 0;
	}
	int res = 0;
	for(int i = 1; i <= n; i++){
		cin >> a[i];
	}
	m = 0;
	for(int i = 1; i <= n; ){
		int j = i;
		b[++m] = a[i];//把一段连续相同的数压成一个数,存在b数组
		while(j <= n && a[j] == b[m]){
			j++;
		}
		i = j;
	}
	int N = n;
	n = m;
	for(int i = 1; i <= n; i++){
		a[i] = b[i];
		cnt[a[i]]++;//出现次数
		r[a[i]] = i;//r[i]是i这个数出现的最右位置
	}
	int maxr = 0;
	for(int i = 1; i <= N; i++){//n的值被改了,不是值域了,用N存原先的n值
		if(cnt[i] >= 2){//如果一个数出现两次以上,那么从1到这个数出现的最右位置都应该是0
			maxr = max(maxr, r[i]);
		}
	}
	for(int i = maxr; i >= 1; i--){
		if(!vis[a[i]]){
			vis[a[i]] = 1;//对这个数进行操作
			res++;
		}
	}
	if(maxr >= n - 1){
		cout << res << '\n';
		return;
	}
	int now = a[n];//当前后缀最小值
	for(int i = n - 1; i >= maxr + 1; i--){
		if(a[i] > now){
			a[i] = 0;
			res++;
			now = 0;
		}
		else{
			now = a[i];
		}
	}
	cout << res << '\n';
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int T = 1;
	cin >> T;
	// for(int i = 1; i <= T; i++){
	// 	num = i;
	// 	solve();
	// }
	while (T--)
	{
		solve();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__night_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值