zoukankan      html  css  js  c++  java
  • CF#537 C. Creative Snap /// DFS

    题目大意:

    给定n k A B为位置长度 复仇者个数 两种花费

    在一段为1~2^n的位置中 某些位置存在一些复仇者

    求消灭所有复仇者的最小花费

    对一段位置可以有两种处理方式

    1.若该段长度至少为2 可以将其分成长度相等的两段分开处理

    2.若该段中不存在复仇者 那么一共只需花费 A

       若该段中存在复仇者 那么花费为 复仇者个数*该段长度*B

    将复仇者位置排序后 对范围[l,r]的一段 利用二分函数就可获得该段中复仇者的个数

    对整段[1,2^n]深搜一下 复杂度不超过O((2^n)<<2)

    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LL long long
    #define mem(i,j) memset(i,j,sizeof(i))
    const int N=1e5+5;
    LL n,k,A,B,a[N];
    LL dfs(int l,int r) {
        int L=lower_bound(a,a+k,l)-a;
        int R=upper_bound(a,a+k,r)-a;
        LL cnt=R-L; // 在l r范围内的复仇者的个数
        if(cnt==0) return A; // 没有复仇者
        if(l==r) return B*cnt; // 已经缩小到一个点 且该点有复仇者
        int m=(l+r)>>1; // 将当前段二分
        return min(B*cnt*(r-l+1),dfs(l,m)+dfs(m+1,r));
        // 直接消灭整段的复仇者 和 二分后再消灭 取小
    }
    int main()
    {
        while(~scanf("%I64d%I64d%I64d%I64d",&n,&k,&A,&B)) {
            for(int i=0;i<k;i++) scanf("%I64d",&a[i]);
            sort(a,a+k); // 将所有复仇者的位置排序 然后才可用二分函数
            printf("%I64d
    ",dfs(1,1<<n));
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    umask设置导致的weblogic中的应用上传的文件没有权限打开
    顺序表查找及其优化(Java)
    前端能力要求
    CSS动画:旋转卡片效果
    CSS居中
    http服务器与https服务器的区别
    phpCURL抓取网页内容
    Node.js概述
    jQuery源码分析
    JavaScript学习书签
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10359038.html
Copyright © 2011-2022 走看看