题解 33:P12845 [蓝桥杯 2025 国 A] 连锁反应
前言
不知道在哪找到了这道题,题解区很多都是 SCC、线段树之类的解法。这里给出一种较为简单的解法。只需要掌握基本的贪心思维即可。
思路
首先按照坐标排序。
不难想到,炸弹的连锁爆炸会将数轴划分为若干个连续引爆区间。区间个数即为所求。
对于任意一个炸弹,我们想知道它在哪个区间,实际上就是想知道所有能连锁引爆它且离它最远的一个炸弹。不妨设
这个东西可以
左界同理。
这样就得到了
排序
代码
ll n,fal[N],far[N],ans,k;
struct node{
ll p,l,r;
}a[N];
bool cmp(node x,node y){
return x.p<y.p;
}
int main(){
n=read();
for(ll i=1;i<=n;i++){
a[i].p=read();
fal[i]=far[i]=i;
a[i].l=a[i].p-read(),a[i].r=a[i].p+read();
//得到其引爆范围
}
sort(a+1,a+n+1,cmp);
for(ll i=2;i<=n;i++){
if(a[i-1].r>=a[i].p){
a[i].r=max(a[i].r,a[i-1].r);
fal[i]=fal[i-1];
}
//处理 far[i]。为了方便直接把 a[i].r 更新为了区间的右界
}
for(ll i=n-1;i>0;i--){
if(a[i+1].l<=a[i].p){
a[i].l=min(a[i].l,a[i+1].l);
far[i]=far[i+1];
}
//同理。
}
for(ll i=1;i<=n;i++){
if(fal[i]>k){
k=far[i];
ans++;
}
//如果 fal[i]>k 说明不能连锁引爆到 i,新开一个区间。
}
write(ans);
return 0;
}