题解:P12648 [KOI 2024 Round 2] 路灯
Heyg_future · · 题解
P12648 [KOI 2024 Round 2] 路灯
题目在这里
哇,这题差点搞死我啊,卡了我好好好久。
Solution
其实本题看似复杂其实一点也不复杂,看似要用各种各样的离奇优化方式,其实就是一道暴力题,只要做法想出来了就直接暴力即可。
看到这种看似要给每个位置遍历一遍的题目,一定要往另一个方向去想。
既然不可以遍历位置,那我们可以遍历到路灯的距离。
首先,路灯所在地的黑暗程度绝对为 废话。
for(int i=1;i<=min(k,n);i++) cout<<"0\n";
k-=n;
然后枚举是否可以与路灯
代码也十分简单。
for(int i=1;i<=l;i++){
for(int j=1;j<=n;j++){
if(a[j]-a[j-1]>i&&f.find(a[j]-i)==f.end())
cout<<i<<"\n",k--,f[a[j]-i]=1;
if(!k) return 0;
if(a[j+1]-a[j]>i&&f.find(a[j]+i)==f.end())
cout<<i<<"\n",k--,f[a[j]+i]=1;
if(!k) return 0;
}
}
注意,要将位置
代码。
#include<iostream>
#include<cmath>
#include<algorithm>
#include<map>
#define int long long
using namespace std;
const int N=405000;
int n,l,k,a[N],s;
map<int,int> f;
signed main(){
cin>>l>>n>>k;
a[0]=-1;
a[n+1]=l+1;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=min(k,n);i++) cout<<"0\n";
k-=n;
if(k<=0) return 0;
for(int i=1;i<=l;i++){
for(int j=1;j<=n;j++){
if(a[j]-a[j-1]>i&&f.find(a[j]-i)==f.end())
cout<<i<<"\n",k--,f[a[j]-i]=1;
if(!k) return 0;
if(a[j+1]-a[j]>i&&f.find(a[j]+i)==f.end())
cout<<i<<"\n",k--,f[a[j]+i]=1;
if(!k) return 0;
}
}
return 0;
}
证明
为什么这个时间复杂度可以通过。
最优复杂度
看似这个方法在一些特殊情况下可能会出现极坏复杂度。如全部路灯挤在一起或每两个之间只相差一个距离时,可能会让它多次从遍历已经没有可以出现点的路灯。但是假设在一种情况中,一共有
记录在这里。
最后,最最最重要的一点,你们知道我为什么卡了这么久吗。
那我问你,十年 OI 一场空,下一句是什么?