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 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...
随机推荐
- Note: Improving Restore Speed for Backup Systems that Use Inline Chunk-Based Deduplication
思路/方法 Measuring restore speed 提出了speed-factor,用以衡量存储速度. Container capping 限制恢复文件时使用的container个数,为了保证 ...
- Ocelot(五)- 流量限制、服务质量
Ocelot(五)- 流量限制.服务质量 作者:markjiang7m2 原文地址:https://www.cnblogs.com/markjiang7m2/p/10965300.html 源码地址: ...
- Spring基本原理模拟(IoC部分)
package ioc; import java.io.File; import java.lang.reflect.Method; import java.util.Collections; imp ...
- 面试d090305知识点准备01
1.1 类成员访问[jL1] 权限 1.2 写个双线程,计算50内的奇偶数 1.3 打印等腰三角形 1.4 运算符优先级 括号,非正负和自增减(右到左),乘除加减,等于不等于,逻辑与和或,然后 ...
- Jmeter 自动化测试报告扩展(转 Todo 需要修正)
首先了解下生成测试报告的过程,我们看到的测试报告是由.jtl格式转换为.html,html报告的样式由extras目录下xsl文件决定.优化测试报告需要分为两部分内容,首先我们要优化输出的测试内容,其 ...
- vue中一些常见错误
一:在抽取路由模块时路径没有更改过来 二:跨域的问题
- Zabbix之CentOS7.3下yum安装Zabbix3.5
Zabbix特点介绍 (此介绍来源于https://www.zabbix.com/documentation/3.4/zh/manual/introduction/features) 概述Zabbix ...
- Unity Gizmos可视化辅助工具
所有gizmo绘制需要在脚本的OnDrawGizmos或OnDrawGizmosSelected里函数完成. OnDrawGizmos在每帧调用.所有在OnDrawGizmos中渲染的gizmos都是 ...
- 迷你迅雷+SqlServer2008r2下载
迷你迅雷下载 http://down.sandai.net/mini/MiniThunderInstaller3.1.1.58.exe SqlServer 2008r2下载 ed2k://|file| ...
- elasticsearch报错:None of the configured nodes are available: []
问题:在内网测试的时候可以正常访问,但是部署到外网上客户端连接elasticsearch报错:None of the configured nodes are available: [] 原因:默认情 ...