Educational Codeforces Round 40 (Rated for Div. 2) G. Castle Defense

本文解析了CodeForces竞赛中G题的解决方案,通过巧妙地处理弓箭手覆盖范围来形成初始防御状态,利用二分查找确定所需弓箭手数量,确保城墙防御不低于特定阈值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://codeforces.com/contest/954/problem/G

题目很巧妙的第一个地方在于把弓箭手讷讷感覆盖到的第一个位置 +1,不能覆盖到的位置 -1,后面的加前面的遍历一遍就形成了初始的防御的状态、然后通过二分检查、看看什么状态能符合、

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class G {

    static final int MAXN = 500005;
    static long[] sum = new long[MAXN]; // 一开始的防御力量
    static long[] prepare = new long[MAXN];  // 预备役弓箭手的布置、、
    static int N, R;
    static long K;

    public static void main(String[] args) throws IOException {
        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        in.nextToken();
        N = (int) in.nval;
        in.nextToken();
        R = (int) in.nval;
        in.nextToken();
        K = (long) in.nval;
        int tmp;
        for (int i = 1; i <= N; i++) {
            in.nextToken();
            tmp = (int) in.nval; // 输入当前城墙上的位置的弓箭手的数量、、、
            sum[Math.max(0, i - R)] += tmp;
            if (i + R < N) {
                sum[i + R + 1] -= tmp;
            }
        }
        for (int i = 1; i <= N; i++) {
            sum[i] += sum[i - 1];  // 遍历形成初始的防御力量分布、
        }

        long l = 0, r = (long) 2e18, mid, ans = 0;
        while (l <= r) {
            mid = (l + r) >> 1;
            if (check(mid)) {
                ans = mid;
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        out.println(ans);
        out.flush();
    }

    private static boolean check(long x) {
        long rest = K, need;
        long add = 0;
        for (int i = 0; i < MAXN; i++) {
            prepare[i] = 0;
        }

        for (int i = 1; i <= N; i++) {
            add += prepare[i];
            if (sum[i] + add < x) {
                need = x - sum[i] - add;
                rest -= need;
                if (rest < 0) {
                    return false;
                }
                prepare[i + 1] += need; // 分配弓箭手防御这一块区域(距离越远防御的效果越好)(下限越高)
                if (i + 2 * R < N) {
                    prepare[i + 2 * R + 1] -= need;  
                }
            }
        }
        return true;

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值