CodeCraft-19 and Codeforces Round #537 (Div. 2)C. Creative Snap

C. Creative Snap

题目链接-C. Creative Snap
洛谷题目链接-CF1111C Creative Snap
在这里插入图片描述
在这里插入图片描述
题目大意
在这里插入图片描述
解题思路
二分+递归

  • 首先我们如果要消灭一段区间[l, r][l,r],我们可以有2种选择:

    1.将整个区间全都毁掉,如果这个区间里没有Avenger,那么花费为A,否则花费为 B* Avenger个数 *区间长度
    2. 将区间分为[l,mid]和[mid+1,r]分开毁掉(即分别取[l,mid]和[mid+1,r]这两个区间,然后累加递归处理后的消耗能量)

  • 如果直接暴力找区间最优解O(2n)肯定会T,所以我们可以先将Avenger的位置排序,再运用lower_bound和upper_bound,这样时间复杂度就是O(nlogn)了,位置数组upper_bound( r )-lower_bound( l )就是[l,r]内英雄的个数

  • dfs递归函数的边界条件是l=r和区间中Avenger数量为0,此时直接返回结果即可

  • 如果其中没有复仇者,直接炸毁即可,要不然把区间分成两段,枚举每一段是直接炸毁还是继续dfs下去,最后取答案的最小值即可

  • upper_bound( r )最后一个小于等于r的数字 lower_bound( l )第一个大于等于l的数字的前一个数字

  • 二分查找的前提是数组有序

二分查找的函数有 3 个:
1.lower_bound(起始地址,结束地址,要查找的数值) 返回的是数值 第一个 出现的位置。
2.upper_bound(起始地址,结束地址,要查找的数值) 返回的是数值 最后一个 出现的位置。
3.binary_search(起始地址,结束地址,要查找的数值) 返回的是是否存在这么一个数,是一个bool值

当然这道题也可以用线段树做,动态开点线段树
但是我太菜了我不会
所以想用线段树做的自己搜搜题解吧,就这样,嘻

附上代码

#include<bits/stdc++.h>
#define lowbit(x) (x &(-x))
using namespace std;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-10;
const int M=1e9+7;
const int N=1e5+5;
typedef long long ll;
typedef pair<int,int> PII;
ll n,k,a,b;
int s[101000];
ll dfs(int l,int r){
	int m=l+((r-l+1)>>1);
	ll ans;
	int num=upper_bound(s+1,s+1+k,r)-lower_bound(s+1,s+1+k,l);
	if(num==0) return ans=a;
	else ans=b*num*(r-l+1);
	if(r-l>=1)
		return ans=min(ans,dfs(l,m-1)+dfs(m,r));
	return ans;
}
int main(){
	
	cin>>n>>k>>a>>b;
	for(int i=1;i<=k;i++)
		cin>>s[i];
	sort(s+1,s+1+k);
	cout<<dfs(1,1<<n)<<endl;
	return 0;
}


发布了78 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Fiveneves/article/details/104437244