题目链接: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 线段树(区间更新 + 点更新)相关推荐

  1. hdu.3308 LCIS(线段树,区间合并+单点更新)

    按照傻崽大神的线段树修炼路线,自己做的第二道区间合并的题. 问题比较简单明了,区间求最长连续上升子序列,但是是需要单点更新的 n个数, m组操作 Q A B 询问[A,B]区间的最长连续上升子序列: ...

  2. SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并

    Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...

  3. hdu 5692 Snacks(dfs序+线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5692 解题思路:这道题是树节点的点权更新,而且涉及到子树,常用的思路是利用dfs序,用线段树来对区间进 ...

  4. hdu 1698(线段树区间更新)

    解题思路:线段树区间更新水题. #include<iostream> #include<cstdio> #include<cstring> using namesp ...

  5. ZOJ 1610 Count the Colors (线段树区间更新)

    题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头 ...

  6. hdu 3966(树链剖分+线段树区间更新)

    传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...

  7. hdu 1698 Just a Hook 线段树区间更新

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 Let us number the consecutive metallic sticks of ...

  8. POJ 2777 ZOJ 1610 HDU 1698 --线段树--区间更新

    直接将这3题 放一起了  今天在做线段树的东西 这3个都是区间更新的 查询方式互相不同 反正都可以放到一起吧 直接先上链接了 touch me touch me touch me 关于涉及到区间的修改 ...

  9. Just a Hook(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 In the game of DotA, Pudge's meat hook is actual ...

  10. hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新

    #1080 : 更为复杂的买卖房屋姿势 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho都是游戏迷,"模拟都市"是他们非常喜欢的一个游戏 ...

最新文章

  1. php读取cookie文件,PHP读取CURL模拟登录时生成Cookie文件的方法,_PHP教程
  2. vuejs基础玩法(基础知识,不喜勿喷!)
  3. java string 转化为date
  4. ubantu14.04下固定ip的配置方法以及问题处理
  5. Linux服务器集群系统(一)--转
  6. (转载)计算机视觉、图像处理中常见的滤波操作
  7. 2018年最值得关注的15大技术趋势
  8. 随想录(在实践中学习kernel代码)
  9. filebeat配置介绍
  10. 智能ai伪原创工具免费
  11. linux触摸屏校准命令,FL2440下触摸屏校准
  12. sip 软电话 java源码,完美的 SIP 软电话
  13. u盘文件意外删除怎么恢复,不小心删了u盘的文件怎么办
  14. git提交代码时账号或密码错误
  15. 容量规划和Region配置
  16. 树莓派 博通BCM2835芯片手册
  17. 如何识破钓鱼邮件攻击
  18. 创建数据表与修改数据表
  19. 聪哥哥有话说之说说《短歌行》
  20. 国产系统独创!Linux环境完美兼容原生安卓App

热门文章

  1. paip.提升效率---request自动绑定domain object
  2. Paip.断点调试MYSQL存储过程跟函数的解决方案大法
  3. paip.提升用户体验与安全性---注册流程总结
  4. (转)300家平台倒闭,BAT纷纷离场,到底什么模式已经全军覆没?
  5. 【优化算法】材料生成算法 (MGA)【含Matlab源码 209期】
  6. 【图像去噪】基于matlab GUI均值+中值图像去噪【含Matlab源码 1815期】
  7. 【基础教程】信噪比+香农公式【1748期】
  8. 毕设题目:Matlab图像检索
  9. 【语音识别】基于matlab傅立叶变换0-9数字语音识别【含Matlab源码 384期】
  10. 张北草原和锡林郭勒草原区别_草原:比您不知道的恶魔还强