BZOJ4141 THUSC2013 魔塔 贪心
没得传送门
考虑当\(Atk\)增大时,\(Def\)一定越来越没用,因为回合数在变少。所以考虑从小到大枚举\(Atk\)然后双指针计算。
设\(f_i(x)\)表示在\(Atk = i\)时,\(Def\)从\(x-1\)到\(x\)时可以减少的血量的数量,易知\(f_i(x) \leq f_i(x - 1) , f_i(x) \leq f_{i-1}(x)\)。对于每一个怪,当\(Atk\)确定之后,它的攻击回合数就确定了。对于\(Atk = i\),一个怪物的攻击力为\(atk\),攻击回合数为\(T\)时,相当于在函数\(f_i(x)\)上\([1,atk]\)区间做一个前缀加\(T\)的操作。当攻击回合数减小的时候也相当于前缀减然后前缀加。
不妨把这个问题变得更形象一点:有若干条线段,左端点为\(1\),右端点不固定,每一条线段都有一个权值。从\(Def = x - 1\)到\(Def = x\)能够减少的血量就是覆盖了\(x\)点的所有线段的权值和。
一件显然的事情是因为\(Def\)在不断变小,所以之前被当前点覆盖的线段在之后也一定被覆盖。
所以我们可以设\(num_i\)表示右端点为\(i\)的所有线段的权值之和,然后我们考虑:当当前的\(Def\)覆盖的线段的权值之和\(\leq cd\)时将\(Def - 1\),然后把\(num_{Def - 1}\)加入,就可以更新出新的权值了。对于删线段和加线段只需要看一下当前加入线段的右端点和\(Def\)的关系并进行更新就可以了。在维护攻击防御值的时候同时维护血量以保证复杂度。
那么最后的问题就是如何快速加入和删除线段,暴力做是\(O(NHp)\)的,但是注意到\(\lceil \frac{Hp}{i} \rceil = \lfloor \frac{Hp - 1}{i} \rfloor + 1\)只有\(\sqrt{Hp}\)种取值,我们可以预处理出每一个转移点,就可以做到\(O(\sqrt{Hp}N)\)了
可能比较卡空间,慎用STL
然后这道题BZOJ上没有SPJ,面向数据编程可以知道:对于所有可行答案,取其中Atk最大的;对于所有Atk一样大的,取Def最大的。
#include<bits/stdc++.h>
//this code is written by Itst
using namespace std;int read(){int a = 0; char c = getchar();while(!isdigit(c)) c = getchar();while(isdigit(c)){a = a * 10 + c - 48; c = getchar();}return a;
}const int _ = 2e6 + 7;
#define PII pair < int , int >
struct node{int nxt , rht , val;
}now[_ * 5 + 5000];
int head[_] , N , CA , CD , cnt , MXD;
long long num[_] , Ans , HP , ATK , DEF , sum , X , Y , Z;void push(int rht , int val , int id){now[++cnt] = (node){head[id] , rht , val};head[id] = cnt;
}void modify(int plc , int val){num[plc] += val;if(Y <= plc){sum += val; Z += (plc - Y) * val;}
}int main(){N = read(); CA = read(); CD = read();for(int i = 1 ; i <= N ; ++i){int h = read() - 1 , a = read() , d = read();for(int j = 1 , pj ; j <= h ; j = pj + 1){pj = h / (h / j);if(j == 1) push(a , h + 1 , d + 1);else push(a , h / j - h / (j - 1) , d + j);}push(a , -1 , h + d + 1);MXD = max(MXD , d);}Ans = 1e18; Y = 1e6; Z = 1;for(X = 1 ; X <= 2e6 ; ++X){for(int i = head[X] ; i ; i = now[i].nxt)modify(now[i].rht , now[i].val);if(X <= MXD) continue;while(Y > 1 && sum < CD){Z += sum; sum += num[--Y];}if(Z + X * CA + Y * CD <= Ans){Ans = Z + X * CA + Y * CD;ATK = X; DEF = Y; HP = Z;}}cout << HP << ' ' << ATK << ' ' << DEF;return 0;
}
转载于:https://www.cnblogs.com/Itst/p/11110944.html
BZOJ4141 THUSC2013 魔塔 贪心相关推荐
- 【牛客NOIP模拟】牛半仙的魔塔(增强版)【贪心】【并查集】
题意:一个魔塔游戏的地图是一棵以 111 为根的树,起点为根,除根外每个结点有一个怪物,给定每个怪物血量.攻击.防御.奖励蓝宝石个数(加防御),勇士的血量.攻击.防御,遇到怪物必须战斗,勇士永远先手, ...
- 贪心(Greedy Algorithm)
贪心(Greedy Algorithm) 贪心 44.通配符匹配 45.跳跃游戏 II 55.跳跃游戏 122.买卖股票的最佳时机II 134.加油站 135.分发糖果 179.最大数 277.搜寻名 ...
- T4牛半仙的魔塔(增强版)
题目描述 牛半仙的妹子被大魔王抓走了,牛半仙为了就他的妹子,前往攻打魔塔. 魔塔为一棵树,牛半仙初始在一号点. 牛半仙有攻击,防御,血量三个属性. 除一号点外每个点都有魔物防守,魔物也有攻击,防御,血 ...
- LCP21 魔塔游戏
LCP 30. 魔塔游戏 难度中等10收藏分享切换为英文接收动态反馈 小扣当前位于魔塔游戏第一层,共有 N 个房间,编号为 0 ~ N-1.每个房间的补血道具/怪物对于血量影响记于数组 nums,其中 ...
- LCP 30.魔塔游戏
题目 小扣当前位于魔塔游戏第一层,共有 N 个房间,编号为 0 ~ N-1.每个房间的补血道具/怪物对于血量影响记于数组 nums,其中正数表示道具补血数值,即血量增加对应数值:负数表示怪物造成伤害值 ...
- leetcode LCP 30. 魔塔游戏
小扣当前位于魔塔游戏第一层,共有 N 个房间,编号为 0 ~ N-1.每个房间的补血道具/怪物对于血量影响记于数组 nums,其中正数表示道具补血数值,即血量增加对应数值:负数表示怪物造成伤害值,即血 ...
- 算法设计与分析第3章 贪心算法
第4章 贪心算法 贪心算法总是作出在当前看来最好的选择.也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择. 贪心算法的基本要素 1.贪心选择性质 所谓贪心选择性质是指所 ...
- 贪心算法单源点最短路径例题c语言源代码,Dijkstra算法是解单源最短路径问题的一个贪心算法...
问题描述 给定一个带权有向图 G=(V,E) ,其中每条边的权是一个非负实数. 另外,还给定 V 中的一个项点,称为源. 现在我们要计算从源到所有其他各项点的最短路径长度. 这里的长度是指路上各边权之 ...
- Too Many Segments CF595D 贪心乱搞
传送门! 比赛的时候没有时间写了,看看了看大佬的代码,学习学习. 一开始实验室大佬说是用差分写的,但是看了代码发现打cf的人大家都是stl狂魔! 贪心思路:区间按照左端点排序,从1~2e5遍历每一个点 ...
- Roundgod and Milk Tea 贪心
这个题好像可以用一种类似与置换的贪心方法来做~ sum记为剩余奶茶,一开始sum等于奶茶和 ans记录已经喝的奶茶数 不用排序,我们就从前往后直接处理,考虑的是每一个班最多可以喝多少杯奶茶 就是从剩余 ...
最新文章
- 自动驾驶场景下的高效激光里程计
- 我在 CMU 的八年博士生涯...........
- asp.net mvc3.0安装失败之终极解决方案
- 识别波峰波谷算法_马丁普林格:波峰-波谷演进法
- python 文件按行读写
- 投票列表排序 - 默认,投票数
- 我的一些学习经验:概述
- 【转载】浅谈嵌入式MCU开发中的三个常见误区
- 关于ArrayList和Vector区别
- 常见线缆接口类型总结
- fifo算法原理及fifo置换算法
- elementui中表格的表头设置背景颜色
- 【蓝桥杯备赛笔记 02】费解的开关
- 测试架构师应该做和不应该做的事情
- 经典的股票量化交易策略(含源码)
- 字节、KB、MB、GB 之间的换算关系 Bps和bps的区别
- 【计算机视觉】:(3)全景图像拼接
- 关于Idea合并不同分支代码你怎么看
- 仿京东图片放大镜动效
- 关于SQL的一点学习