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 = ;
const int maxn = + ;
const int N = ;
int level[maxn << ] , Exp[maxn << ] , col[maxn << ];
double Min[maxn << ];
int Need[N];
void PushUp(int rt)
{
level[rt] = max(level[rt << ] , level[rt << | ]);
Exp[rt] = max(Exp[rt << ] , Exp[rt << | ]);
Min[rt] = min(Min[rt << ] , Min[rt << | ]);
}
void PushDown(int rt)
{
if(col[rt]) {
col[rt << ] += col[rt];
col[rt << | ] += col[rt];
Min[rt << ] -= col[rt];
Min[rt << | ] -= col[rt];
Exp[rt << ] += level[rt << ] * col[rt];
Exp[rt << | ] += level[rt << | ] * col[rt];
col[rt] = ;
}
}
void build(int l , int r , int rt)
{
if(l == r) {
level[rt] = ;
Exp[rt] = ;
Min[rt] = Need[] * 1.0;
return;
}
col[rt] = ;
int m = (l + r) >> ;
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] + ])
level[rt]++; //升级英雄
Min[rt] = (Need[level[rt] + ] - Exp[rt]) * 1.0 / level[rt]; //更新Min标记
return;
}
PushDown(rt);
int m = (l + r) >> ;
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] + ])
level[rt]++;
Min[rt] = (Need[level[rt] + ] - 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) >> ;
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) >> ;
if(L > m)
return query(L , R , rson);
else if(R <= m)
return query(L , R , lson);
else
return max(query(L , R , lson) , query(L , R , rson));
}
int main()
{
int T , K , n , m , i , a , b , c;
char ch[];
cin >> T;
for(int k = ; k <= T ; k++)
{
printf("Case %d:\n" , k);
scanf("%d %d %d" , &n , &K , &m);
for(i = ; i <= K ; i++)
scanf("%d" , &Need[i]);
Need[i] = INF;
build( , n , );
while(m--) {
scanf("%s" , ch);
if(ch[] == 'W') {
scanf("%d %d %d" , &a , &b , &c);
update(a , b , c , , n , );
} else if(ch[] == 'Q') {
scanf("%d %d" , &a , &b);
printf("%d\n" , query(a , b , , n , ));
}
}
puts("");
}
return ;
}
HDU3954 线段树(区间更新 + 点更新)的更多相关文章
- HDU 2795 线段树区间最大值,单点更新+二分
Billboard Time Limit: 20000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- XOR on segment(线段树区间异或更新)
原题传送门 本题大意:给定n个数字和m个操作,操作共有两种,第一种是求解区间l到r上元素的和,第二种是将区间l到r的元素都异或一个x,作为某个位置的新值. 很容易想到线段树维护区间和,但是我们发现,在 ...
- 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间合并(单点更新、区间查询)
P4513 小白逛公园 题目背景 小新经常陪小白去公园玩,也就是所谓的遛狗啦… 题目描述 在小新家附近有一条“公园路”,路的一边从南到北依次排着nn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩 ...
- hdu 1116 敌兵布阵 线段树 区间求和 单点更新
线段树的基本知识可以先google一下,不是很难理解 线段树功能:update:单点增减 query:区间求和 #include <bits/stdc++.h> #define lson ...
- HDU 1394:Minimum Inversion Number(线段树区间求和单点更新)
http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number Problem Description The in ...
- hdu 3308 线段树 区间合并+单点更新+区间查询
LCIS Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- hdu 1166 线段树 区间求和 +单点更新 CD模板
题目链接 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并
Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...
- HDU 1556 Color the ball(线段树区间更新)
Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...
随机推荐
- linq分页扩展
直接上代码了 public static List<T> ToPagedList<T>(this IEnumerable<T> allItems, int page ...
- C#——各种参数,扩展方法
余近日复习C#之基础知识,故作一随笔,也是对此前几篇博客中所记录的传值参数相关内容之汇总,还望诸位加以批评指正. 该博客包括以下内容: 传值参数 引用参数 输出参数 数组参数 具名参数 可选参数 扩展 ...
- Machine Learning-KNN
思路:如果一个样本在特征空间中的k个最相近的样本中大多数属于某个类别,则该样本也属于该类别: 这段话中涉及到KNN的三要素:K.距离度量.决策规则 K:KNN的算法的结果很大程度取决于K值的选择: I ...
- rlwrap: command not found和解决linux下sqlplus 提供浏览历史命令行的功能
rlwrap工具可以解决linux下sqlplus 提供浏览历史命令行的功能,和删除先前输入错误的字母等问题 1.安装 需要readline包 这个安装光盘就有 [root@asm RedHat]# ...
- Python中list的复制及深拷贝与浅拷贝探究
在Python中,经常要对一个list进行复制.对于复制,自然的就有深拷贝与浅拷贝问题.深拷贝与浅拷贝的区别在于,当从原本的list复制出新的list之后,修改其中的任意一个是否会对另一个造成影响,即 ...
- 【常见Web应用安全问题】
Web应用程序的安全性问题依其存在的形势划分,种类繁多,这里不准备介绍所有的,只介绍常见的一些. 常见Web应用安全问题安全性问题的列表: 1.跨站脚本攻击(CSS or XSS, Cross Sit ...
- EOS多节点同步代码分析
EOS version: 1.0.7 一. 配置文件的修改 EOS的节点同步流程是通过p2p来完成,在nodeos的配置文件config.ini中填写,其默认路径为~/.local/share/eos ...
- AT2160 へんなコンパス / Manhattan Compass
传送门 乍一看像是一个计算几何,然后想到了BFS,但是苦于无奈\(O(n^2)\)不会优化 然后以下参考zjq_shadow大佬的思路 显然发现曼哈顿距离很麻烦,除了暴力枚举貌似没什么很好的办法 考虑 ...
- screen命令常用参数使用
screen简要说明 screen 会话命令可以保持本地和服务器断开后,程序继续在服务器上运行,并且运行结束后,输出最后的结果.功能结果相当于 nohup command &,但是功能远比no ...
- Ehab and subtraction(思维题)
time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...