题目地址: https://codeforces.com/problemset/problem/1111/C
题目大意:
给你一个长度为2^n的区间,求摧毁这个区间费用最小几何?有如下两种操作任君选择,其一:当前区间一分为二分别摧毁,其二:直接摧毁当前区间。如果当前区间里面没有Avenger, 那么摧毁当前区间费用为A,否则为BLNa,其中L为当前区间长度,Na为当前区间Avenger数量。
解题思路:
鉴于区间较大,不能用树状数组和线段树模拟。实际上并没有模拟的必要,因为区间长度是2的幂,只需要向下递归,二分地求每个区间最小摧毁花费就得了(区间可以直接摧毁或者一分为二摧毁)。难点是怎么快速求出区间的Avenger的数量。只需要把Avenger的位置存入vector内,根据下标二分查找数量就可以了。由于Avenger总数较小(1e5),递归不会跑满, 不会超时。
这里是引用
# include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
typedef long long ll;
int n, k, A, B;
int num[maxn];
ll dfs(int l, int r){
int mid = (l+r) / 2;
int tot = upper_bound(num+1, num+1+k, r) - lower_bound(num+1, num+1+k, l);
ll ans;
if(!tot) return ans = A;
ans = 1ll*B*(r-l+1)*tot;
if(r - l >= 1) ans = min(ans, dfs(l, mid) + dfs(mid+1, r));
return ans;
}
int main(){
std::ios::sync_with_stdio(false);
while(cin >> n >> k >> A >> B){
for(int i = 1; i <= k; ++i) cin >> num[i];
sort(num+1, num+1+k);
cout << dfs(1, 1 << n) << endl;
}
return 0;
}