小工具知识网

当前位置: 首页 > 行业知识 > [蓝桥杯2023初赛] 整数删除

行业知识

[蓝桥杯2023初赛] 整数删除

2026-10-21 17:06:09 来源:互联网转载

���定一个长度为 N 的整数数列:A1, A2, ... , AN。你要重复以下操作 K 次:

()

每次选择数列中最小的整数(如果最小值不止一个,选择最靠前的),将其删除。

并把与它相邻的整数加上被删除的数值。

()

输出 K 次操作后的序列。

输入格式

第一行包含两个整数 N 和 K。

第二行包含 N 个整数,A1, A2, ... , AN。

对于 20% 的数据,1 ≤ K < N ≤ 10000。

对于 100% 的数据,1 ≤ K < N ≤ 5 × 1e5,0 ≤ Ai ≤ 1e8。

输出格式

输出 N − K 个整数,中间用一个空格隔开,代表 K 次操作后的序列。

输入样例

5 31 4 2 8 7

输出样例

17 7

数据范围与提示

数列变化如下,中括号里的数是当次操作中被选择的数:

[1] 4 2 8 7

5 [2] 8 7

[7] 10 7

17 7

解析: 

        用优先队列维护每个值和其对应的下标,并且双链表储存整个区间。因为每次取出的最小值,其相邻的元素要加上这个最小值,但是队列中无法取出,所以用 cnt 数组记录每个元素需要增加的值。

        每次取出队头的元素,如果这个 cnt 数组中没有记录这个元素,则从链表中删除,并且 cnt 记录其相邻元素所要增加的元素。如果 cnt 中记录了这个元素,则加上 cnt 中记录的增加值,然后放回队列中。

        当队列中元素为 n-k 时跳出循环,然后遍历 cnt 将其剩余没有计算的增加值加到队列中剩余的数中。由于剩余元素仍然按照下标的大小排序,所以按照下标输出即可。

        我们可知,时间复杂度为线性的。

代码:

#includeusing namespace std;const int N=5e5+10;int n,k;priority_queueq;int pre[N],ne[N];long long cnt[N],a[N],t;int main(){scanf("%d%d",&n,&k);for(int i=1;in-k){long long x=q.top().first;int id=q.top().second;q.pop();if(cnt[id]){q.push({x+cnt[id],id});cnt[id]=0;}else{int left=pre[id],right=ne[id];cnt[left]+=x;cnt[right]+=x;ne[left]=right;pre[right]=left;}}while(q.size()){long long x=q.top().first;int id=q.top().second;q.pop();a[id]=x+cnt[id];}for(int i=1;i

上一篇:电梯机房在楼顶哪里?

下一篇:dota怎么设置国服服务器?