HDU3954 线段树(区间更新 + 点更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3954 , 一道比较好的线段树题,值得做。
题目是NotOnlySuccess大神出的,借此题来膜拜一下大神,毕竟我学的就是NotOnlySuccess线段树,ORZ。
这道题比较复杂,如何判断一波经验加成之后是否有英雄需要升级,如果升级需要如何处理,怎样维护Exp的区间最值,都是这道题的难点。
我在网上百度了别人的题解才敲的出来,具体方法如下:
线段树上三个数组:level[]表示等级的区间最值;Exp[]表示经验的区间最值; Min标记表示最少需要多少经验基数使该区间有英雄可以升级(刷怪得到的经验 = e * 等级,e就是经验基数)。
可知每个区间的等级最高的英雄其经验值也是最高的,所以对于每次更新,Exp[rt] += level[rt] * e。对于每次更新,如果当前区间有英雄可以升级,即 e >= Min[rt],那么就把这个区间实行点更新,枚举每个叶子节点检查英雄是否需要升级,英雄升级以后要更新Min标记;如果没有英雄升级,就进行正常的区间更新(更新Min标记,更新Exp值)。
#include <iostream> #include <cstdio> #include <vector> #include <cmath> #include <string> #include <string.h> #include <algorithm> using namespace std; #define LL __int64 #define eps 1e-8 #define INF INT_MAX #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int MOD = 10000007; const int maxn = 10000 + 5; const int N = 12; int level[maxn << 2] , Exp[maxn << 2] , col[maxn << 2]; double Min[maxn << 2]; int Need[N]; void PushUp(int rt) {level[rt] = max(level[rt << 1] , level[rt << 1 | 1]);Exp[rt] = max(Exp[rt << 1] , Exp[rt << 1 | 1]);Min[rt] = min(Min[rt << 1] , Min[rt << 1 | 1]); } void PushDown(int rt) {if(col[rt]) {col[rt << 1] += col[rt];col[rt << 1 | 1] += col[rt];Min[rt << 1] -= col[rt];Min[rt << 1 | 1] -= col[rt];Exp[rt << 1] += level[rt << 1] * col[rt];Exp[rt << 1 | 1] += level[rt << 1 | 1] * col[rt];col[rt] = 0;} } void build(int l , int r , int rt) {if(l == r) {level[rt] = 1;Exp[rt] = 0;Min[rt] = Need[2] * 1.0;return;}col[rt] = 0;int m = (l + r) >> 1;build(lson);build(rson);PushUp(rt); } void level_up(int e , int l , int r , int rt) {if(l == r) { //更新到叶子节点Exp[rt] += e * level[rt];while(Exp[rt] >= Need[level[rt] + 1])level[rt]++; //升级英雄Min[rt] = (Need[level[rt] + 1] - Exp[rt]) * 1.0 / level[rt]; //更新Min标记return;}PushDown(rt);int m = (l + r) >> 1;level_up(e , lson);level_up(e , rson);PushUp(rt); } void update(int L , int R , int e , int l , int r , int rt) {if(l == r) {Exp[rt] += e * level[rt];while(Exp[rt] >= Need[level[rt] + 1])level[rt]++;Min[rt] = (Need[level[rt] + 1] - Exp[rt]) * 1.0 / level[rt];return;}if(L <= l && R >= r) {if(Min[rt] - e > 0.00) { //没有英雄升级Min[rt] -= e;col[rt] += e;Exp[rt] += level[rt] * e; } else { //有英雄升级 PushDown(rt); level_up(e , l , r , rt);PushUp(rt);}return;}PushDown(rt);int m = (l + r) >> 1;if(L > m)update(L , R , e , rson);else if(R <= m)update(L , R , e , lson);else {update(L , R , e , lson);update(L , R , e , rson);}PushUp(rt); } int query(int L , int R , int l , int r , int rt) {if(L <= l && R >= r) {return Exp[rt];}PushDown(rt);int m = (l + r) >> 1;if(L > m)return query(L , R , rson);else if(R <= m)return query(L , R , lson);elsereturn max(query(L , R , lson) , query(L , R , rson)); } int main() {int T , K , n , m , i , a , b , c;char ch[3];cin >> T;for(int k = 1 ; k <= T ; k++){printf("Case %d:\n" , k);scanf("%d %d %d" , &n , &K , &m);for(i = 2 ; i <= K ; i++)scanf("%d" , &Need[i]);Need[i] = INF;build(1 , n , 1);while(m--) {scanf("%s" , ch);if(ch[0] == 'W') {scanf("%d %d %d" , &a , &b , &c);update(a , b , c , 1 , n , 1);} else if(ch[0] == 'Q') {scanf("%d %d" , &a , &b);printf("%d\n" , query(a , b , 1 , n , 1));}}puts("");}return 0; }
转载于:https://www.cnblogs.com/H-Vking/p/4297983.html
HDU3954 线段树(区间更新 + 点更新)相关推荐
- hdu.3308 LCIS(线段树,区间合并+单点更新)
按照傻崽大神的线段树修炼路线,自己做的第二道区间合并的题. 问题比较简单明了,区间求最长连续上升子序列,但是是需要单点更新的 n个数, m组操作 Q A B 询问[A,B]区间的最长连续上升子序列: ...
- SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并
Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...
- hdu 5692 Snacks(dfs序+线段树区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5692 解题思路:这道题是树节点的点权更新,而且涉及到子树,常用的思路是利用dfs序,用线段树来对区间进 ...
- hdu 1698(线段树区间更新)
解题思路:线段树区间更新水题. #include<iostream> #include<cstdio> #include<cstring> using namesp ...
- ZOJ 1610 Count the Colors (线段树区间更新)
题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头 ...
- hdu 3966(树链剖分+线段树区间更新)
传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...
- hdu 1698 Just a Hook 线段树区间更新
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 Let us number the consecutive metallic sticks of ...
- POJ 2777 ZOJ 1610 HDU 1698 --线段树--区间更新
直接将这3题 放一起了 今天在做线段树的东西 这3个都是区间更新的 查询方式互相不同 反正都可以放到一起吧 直接先上链接了 touch me touch me touch me 关于涉及到区间的修改 ...
- Just a Hook(线段树区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 In the game of DotA, Pudge's meat hook is actual ...
- hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新
#1080 : 更为复杂的买卖房屋姿势 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho都是游戏迷,"模拟都市"是他们非常喜欢的一个游戏 ...
最新文章
- php读取cookie文件,PHP读取CURL模拟登录时生成Cookie文件的方法,_PHP教程
- vuejs基础玩法(基础知识,不喜勿喷!)
- java string 转化为date
- ubantu14.04下固定ip的配置方法以及问题处理
- Linux服务器集群系统(一)--转
- (转载)计算机视觉、图像处理中常见的滤波操作
- 2018年最值得关注的15大技术趋势
- 随想录(在实践中学习kernel代码)
- filebeat配置介绍
- 智能ai伪原创工具免费
- linux触摸屏校准命令,FL2440下触摸屏校准
- sip 软电话 java源码,完美的 SIP 软电话
- u盘文件意外删除怎么恢复,不小心删了u盘的文件怎么办
- git提交代码时账号或密码错误
- 容量规划和Region配置
- 树莓派 博通BCM2835芯片手册
- 如何识破钓鱼邮件攻击
- 创建数据表与修改数据表
- 聪哥哥有话说之说说《短歌行》
- 国产系统独创!Linux环境完美兼容原生安卓App
热门文章
- paip.提升效率---request自动绑定domain object
- Paip.断点调试MYSQL存储过程跟函数的解决方案大法
- paip.提升用户体验与安全性---注册流程总结
- (转)300家平台倒闭,BAT纷纷离场,到底什么模式已经全军覆没?
- 【优化算法】材料生成算法 (MGA)【含Matlab源码 209期】
- 【图像去噪】基于matlab GUI均值+中值图像去噪【含Matlab源码 1815期】
- 【基础教程】信噪比+香农公式【1748期】
- 毕设题目:Matlab图像检索
- 【语音识别】基于matlab傅立叶变换0-9数字语音识别【含Matlab源码 384期】
- 张北草原和锡林郭勒草原区别_草原:比您不知道的恶魔还强