CF-1111C-Creative Snap

前两天过年,所以两天前的比赛题目现在才来回顾。

这题是一个最平常的递归,加一个剪枝。题目说如果一段距离没有复仇者看守,消耗的能量为A,A一定是正整数。由此可知对于没有复仇者看守的段,不拆一定比拆成两半划得来。只有当这段距离有复仇者看守时,才比较拆开来划算还是不拆划算;

复仇者最多只有1e5个,所以不会超时。比赛的时候糊涂了,想到了但是算错了复杂度。没做;

C - Creative Snap GNU C++11 Accepted 155 ms 400 KB
#include "bits/stdc++.h"
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 5;
int arr[MAXN];
int n, m, a, b;
// 求摧毁[l, r]这个段最少消耗的能量
LL minPow(int l, int r) {
    int na = lower_bound(arr, arr + m, r + 1) - lower_bound(arr, arr + m, l);
    if (na == 0) {
        return a;
    }
    LL ans = (r - l + 1LL) * na * b;
    if (r != l) {
        int mid = l + r >> 1;
        ans = min(ans, minPow(l, mid) + minPow(mid + 1, r));
    }
    return ans;
}
int main() {
    scanf("%d%d%d%d", &n, &m, &a, &b);
    for (int i = 0; i < m; i++) {
        scanf("%d", &arr[i]);
    }
    sort(arr, arr + m);
    printf("%lld\n", minPow(1, 1 << n));
    return 0;
}

第一次敲这个代码的时候用了一个multiset<int>来代替arr数组。后来发现lower_bound之后返回的迭代器不能相减。可能是之前看别人用lower_bound返回的迭代器减另一个迭代器受到了误解。只要在内存中连续存储的容器的迭代器才能相减,而multiset在内存中不连续,不能迭代器相减。

原文地址:https://www.cnblogs.com/Angel-Demon/p/10354028.html

时间: 2024-08-30 18:17:44

CF-1111C-Creative Snap的相关文章

Codeforces 1111C Creative Snap分治+贪心

Creative Snap C. Creative Snap time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Thanos wants to destroy the avengers base, but he needs to destroy the avengers along with their base. Let we

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) #inc

C. Creative Snap(分治)

只用考虑对于任意一段,直接炸掉好还是分成两段好,看见0的直接返回A 然后用了在整个区间上的二分搜索,这个一开始想复杂了,还想把a数组分成小区间,但是后来发现没必要 #include<bits/stdc++.h> using namespace std; typedef long long ll; ll a[100010]; ll n,k,A,B; ll cal(ll l,ll r) { //最后一个小于等于r的数字 //第一个大于等于l的数字的前一个数字 return upper_bound(

CF1111C Creative Snap

思路: 分治,递归实现就可以.不一定非得用前缀和,直接用一个数组记录avengers的位置然后二分即可.写的有点复杂了. 实现: 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 ll n, k, A, B; 5 ll dfs(ll l, ll r, vector<ll>& K, vector<ll>& V, vector<ll>&

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

[链接] 我是链接,点我呀:) [题意] 横坐标1..2^n对应着2^n个复仇者的基地,上面有k个复仇者(位置依次给出). 你是灭霸你要用以下方法消灭这k个复仇者: 一开始你获取整个区间[1..2^n] 假设你当前获取的区间为[l,r] mid = (l+r)/2 那么你每次有两种选择 1.将整个区间全都毁掉,如果这个区间里没有复仇者,那么花费为A,否则花费为B复仇者个数区间长度 2.将区间分为[l,mid]和[mid+1,r]分开毁掉(即分别获取[l,mid]和[mid+1,r]这两个区间,然

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

A. Superhero Transformation 水题,注意两个字符串可能长度不相等. #include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=100010; map<char ,int >m; int main(){ m['a']=m['e']=m['i']=m['o']=m['u']=1;

codeforces contest 1111

A. Superhero Transformation 题意: 元音和元音,辅音和辅音字母之间可以互相转换,问两个字符串是否想同: 题解:直接判断即可: 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1010; 4 char s[N]; 5 int n,m,vis1[N],vis2[N]; 6 int judge(char x){return x=='a'||x=='e'||x=='i'||x=='o'||x=='

CF#462 div1 D:A Creative Cutout

CF#462 div1 D:A Creative Cutout 题目大意: 原网址戳我! 题目大意: 在网格上任选一个点作为圆中心,然后以其为圆心画\(m\)个圆. 其中第\(k\)个圆的半径为\(\sqrt{k}\),\(m\)个圆的编号依次为\(1\)~\(m\). 定义一个格点的美妙值\(g(x,y)\)为包含了它的所有圆的编号之和. 定义\(f(n)\)为:当画了\(n\)个圆时,\(f(n) = \sum_{i,j\in R} g(i,j)\). 现在非常变态的问你一个非常无聊的恶心问

微信 {&quot;errcode&quot;:40029,&quot;errmsg&quot;:&quot;invalid code, hints: [ req_id: Cf.y.a0389s108 ]&quot;}

{"errcode":40029,"errmsg":"invalid code, hints: [ req_id: Cf.y.a0389s108 ]"} 问题:微信网页授权后,获取到 openid 了,一刷新又没了 微信网页授权获取到的 code 只能使用一次(5分钟内有效),使用一次后,马上失效. 页面授权跳转成功,根据 code 也换取到 openid 了. 此时刷新页面,并不会再次进行授权,而是直接刷新了一下上一次授权跳转后的链接,带的还是