专栏文章

题解:CF2037F Ardent Flames

CF2037F题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mir31w5r
此快照首次捕获于
2025/12/04 14:56
3 个月前
此快照最后确认于
2025/12/04 14:56
3 个月前
查看原文
二分答案,设攻击了 kk 次。
因为只能是在同一个位置 pp 攻击,所以第 ii 个敌人每次攻击需要受到至少 ti=hikt_i=\lceil\frac{h_i}{k}\rceil 的伤害,因此 pp 的范围就是 [xi(mt[i]),xi+(mt[i])][x_i-(m-t[i]),x_i+(m-t[i])],若 m<tim < t_i 则一定无法击败第 ii 个敌人。
这样就转化成了 nn 个区间的覆盖问题,问是否有一个点被覆盖了至少 kk 次。
离散化加差分轻松搞定,复杂度为 O(nlog(n)log(V))O(n\log(n)\log(V))
CPP
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5,inf=1e9;
int n,m,k;
int h[N],x[N],t[N];
int tot;
int b[N],c[N];
bool check(int k)
{
    tot=0;
    for(int i=1;i<=n;i++) 
    {
        t[i]=(h[i]+k-1)/k;
        if(t[i]<=m) 
        {
            c[++tot]=x[i]-(m-t[i]);
            c[++tot]=x[i]+(m-t[i])+1;
        }
    }
    sort(c+1,c+tot+1);
    tot=unique(c+1,c+tot+1)-c-1;
    for(int i=1;i<=tot;i++) b[i]=0;
    for(int i=1;i<=n;i++)
    {
        if(t[i]<=m)
        {
            int l=lower_bound(c+1,c+tot+1,x[i]-(m-t[i]))-c;
            int r=lower_bound(c+1,c+tot+1,x[i]+(m-t[i])+1)-c;
            b[l]++,b[r]--;
        }
    }
    for(int i=1;i<=tot;i++) b[i]+=b[i-1];
    for(int i=1;i<=tot;i++) if(b[i]>=k) return 1;
    return 0;
}
void solve()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) cin>>h[i];
    for(int i=1;i<=n;i++) cin>>x[i];
    int l=1,r=inf,mid,ans=-1;    
    while(l<=r)
    {
        mid=l+r>>1;
        if(check(mid)) r=mid-1,ans=mid;
        else l=mid+1;
    }
    cout<<ans<<'\n';
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...