Trash Problem

本文探讨如何通过最少的操作将序列中的垃圾移动到两个特定坐标,利用x+1和x-1操作,优化策略聚焦于找到最优位置组合以减少移动总距离。

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

 

 

传送门 

题意:

一段序列,每一个数字的大小代表坐标位置,这些坐标位置上都有垃圾,要求将这一段序列的数字最终通过x + 1, x - 1操作移动到小于等于2个位置,垃圾移动到同一个坐标位置就可以和那个坐标位置一起移动,问最小的移动数量。

思路:

通过观察,两个以内包括两个,直接0, 其他,最后移动到只剩两个最优,那肯定是有两个要选择的,通过观察发现我不管选哪两个,最后都是整体长度的减去其中每一个相邻的位置差,头和尾的差就是整体长度,要使最小,中间相邻差最大即可。

这里注意编辑代码,可能会有一种编辑方法是不断声明迭代器,通过++ --操作,但是这样会超时,效率太低了,有两个next(it), prev(it) 这两个是针对迭代器的++ --的最快效率了

#include <bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false);
using namespace std;

typedef long long ll;

int n, q, op, x;
set<int> se;
multiset<int> mus;
ll sum = 0;

void add(int x)
{
	se.insert(x);
	auto it = se.find(x);
	if (next(it) != se.end())
	{
		sum += *next(it) - *it;	//这里用next效率快很多
		mus.insert(*next(it) - *it);
	}
	if (it != se.begin())
	{
		sum += *it - *prev(it);
		mus.insert(*it - *prev(it));
	}
	if (next(it) != se.end() && it != se.begin())
	{
		sum -= *next(it) - *prev(it);
		mus.erase(mus.find(*next(it) - *prev(it)));
	}
}

void erase(int x)
{
	auto it = se.find(x);
	if (next(it) != se.end())
	{
		sum -= *next(it) - *it;
		mus.erase(mus.find(*next(it) - *it));
	}
	if (it != se.begin())
	{
		sum -= *it - *prev(it);
		mus.erase(mus.find(*it - *prev(it)));
	}
	if (next(it) != se.end() && it != se.begin())
	{
		sum += *next(it) - *prev(it);
		mus.insert(*next(it) - *prev(it));
	}
	se.erase(x);
}

int getAns()
{
	if (se.size() <= 2)
		return 0;
	return sum - *(--mus.end());
}


#include <bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false);
using namespace std;

typedef long long ll;

int main()
{
	/*IOS; cin.tie(0), cout.tie(0);*/
	cin >> n >> q;
	for (int i = 1; i <= n; ++i)
	{
		int temp;
		cin >> temp;
		add(temp);
	}
	cout << getAns() << endl;

	while (q--)
	{
		cin >> op >> x;
		if (op == 1)
		{
			add(x);
			cout << getAns() << endl;
		}
		else
		{
			erase(x);
			cout << getAns() << endl;
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值