题解:P12085 [蓝桥杯 2023 省 B] 整数删除
TB__QGSS__423 · · 题解
本题的优秀题解有很多,大致思路是用双向链表储存数列,方便进行加值操作,再用优先队列维护 某种程度上代替了警示后人
part 1.思维难点
这道题目的核心难点在于,通过维护一个数据版本来判断优先队列中的数据能不能用。相信很多人做题时,能顺利想到用优先队列维护
part 2.代码实现注意
我看身边挺多人被代码实现卡过,因此痛批蓝桥杯。
- 最常提的,不开 long long 见祖宗,因为本题的
A_i 加值后最大能达到5\times10^{13} 。 - 在给左右两边的数加值时,注意判断链表的边界情况,不然你就会得到 UB 和 TLE。
- 写双向链表这玩意,要注意分清左右,不要搞混了,感觉实在调不出来,可以试试直接重写,思路更清晰。
part 3.总结
写题多注意数据的可能上限。写链表小心边界,注意实现。不长的代码调不出不要死扣,试试重写。记住维护数据版本这种队列的小 trick。
感谢 @cuberYida、@rekcA_h 为文章提供的意见,附上不怎么好看的代码。
::::info[code]
#include<bits/stdc++.h>
#define co const
#define lx x<<1
#define rx x<<1|1
#define ll long long
#define pii pair<int,int>
#define pll pair<long long,long long>
using namespace std;
co int N=5e5+5;
int n,k,bh[N],fl[N];
ll a[N];
struct List{
int l,r;
}lst[N];
struct node{
int id;
int b;
ll val;
bool operator < (const node cmp) const{
return val==cmp.val?id>cmp.id:val>cmp.val;
}
};
priority_queue<node> q;
int main() {
cin>>n>>k;
for(int j=1; j<=n; j++){
cin>>a[j];
q.push({j,0,a[j]});
lst[j].l=j-1,lst[j].r=j+1;
}
for(int j=1; j<=k; j++){
while(!q.empty() && q.top().b!=bh[q.top().id]) q.pop();
int x=q.top().id;
fl[x]=1;
q.pop();
if(lst[x].l>=1){
lst[lst[x].l].r=lst[x].r;
bh[lst[x].l]=j;
a[lst[x].l]+=a[x];
q.push({lst[x].l,j,a[lst[x].l]});
}
if(lst[x].r<=n){
lst[lst[x].r].l=lst[x].l;
bh[lst[x].r]=j;
a[lst[x].r]+=a[x];
q.push({lst[x].r,j,a[lst[x].r]});
}
}
for(int j=1; j<=n; j++){
if(!fl[j]) cout<<a[j]<<' ';
}
return 0;
}
::::