洛谷题解:P12085 [蓝桥杯 2023 省 B] 整数删除

先读题目:把给出的数列的最小值删移,并把它左右两边数相加这个数,重复 k k k 次,最后输出数列。

思路

循环 k k k 次,把每个最小值删移,给左右两边的数加上这个数。
代码:

#include
using namespace std;
int n;
vector<int>a(100001);
int main(){
	cin>>n;
	a[0]=INT_MAX;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int i=1;i<=k;i++){
		int x,minn=INT_MIN;
		for(int i=1;i<=a.size();i++)
			if(a[i]>minn)minn=a[i],x=i;
		a[x-1]+=a[x];
		a[x+1]+=a[x];
		a.erase(a.begin()+x;
	}
	for(int i=1;i<=n;i++)
		cout<<a[i];
	return 0;
}

TLE!

优化

用优先队列(priority_queue)求最小值。

拓展:
在 C++ 中,priority_queue 是一个模板类,定义在头文件中,有三个模板参数:元素类型、容器类型和比较函数类型(可选)。默认情况下,它使用 std::vector 作为其底层容器。

优先队列会打乱顺序,所以要用 vector> 记录顺序和值。
可给左右两边的数加上这个数怎么办?可以用数组存编号啊!

总结

大模拟+堆+链表的好题。

下面来看看 c++STL 库的魅力。

#include
using namespace std;
typedef long long ll;
const int MAXN = 5e5 + 10;
typedef pair<ll, int> pii;
ll a[MAXN];
int ln[MAXN], rn[MAXN];
bool d[MAXN];
int n,k;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    //输入
	cin>>n>>k;
    priority_queue<pii, vector<pii>, greater<pii>> pq;// 堆/优先队列
    for (int i=1;i<=n;i++) {
        cin>>a[i];//输入
        pq.emplace(a[i], i);//放入优先队列
        //数组记录
        ln[i] = i - 1;
        rn[i] = i + 1;
    }
    //开头和结尾的修正
    ln[1]=-1;
    rn[n]=-1;
    while (k--) {
        pii c;
        do {
            c = pq.top();
            pq.pop();
        } while (d[c.second] || a[c.second] != c.first);//没走过或对不上
        //方便计算
        int p = c.second;
        ll val = c.first;
        //调整左右
        //不是第一个,就把左边增加和调整
        if (ln[p] != -1) {
            int left_pos = ln[p];
            a[left_pos] += val;
            pq.emplace(a[left_pos], left_pos);
            rn[left_pos] = rn[p];
        }
        //不是最后一个,就把右边增加和调整
        if (rn[p] != -1) {
            int right_pos = rn[p];
            a[right_pos] += val;
            pq.emplace(a[right_pos], right_pos);
            ln[right_pos] = ln[p];
        }
        d[p] = true;//标记
    }
    vector<ll> res;
    for (int i = 1; i <= n;i++) 
        if (!d[i])//没有被标记就是没有删除,所以加入答案
            res.push_back(a[i]);
    //输出
    for (size_t i=0;i<res.size();i++) {
        if (i!=0) cout<<" ";
        cout<<res[i];
    }
    cout<<endl;//末尾换行
    return 0;//完结散花
}

原文链接

你可能感兴趣的:(题解,蓝桥杯)