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

  1. HDU 2795 线段树区间最大值,单点更新+二分

    Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  2. XOR on segment(线段树区间异或更新)

    原题传送门 本题大意:给定n个数字和m个操作,操作共有两种,第一种是求解区间l到r上元素的和,第二种是将区间l到r的元素都异或一个x,作为某个位置的新值. 很容易想到线段树维护区间和,但是我们发现,在 ...

  3. 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间合并(单点更新、区间查询)

    P4513 小白逛公园 题目背景 小新经常陪小白去公园玩,也就是所谓的遛狗啦… 题目描述 在小新家附近有一条“公园路”,路的一边从南到北依次排着nn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩 ...

  4. hdu 1116 敌兵布阵 线段树 区间求和 单点更新

    线段树的基本知识可以先google一下,不是很难理解 线段树功能:update:单点增减 query:区间求和 #include <bits/stdc++.h> #define lson ...

  5. HDU 1394:Minimum Inversion Number(线段树区间求和单点更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number Problem Description   The in ...

  6. hdu 3308 线段树 区间合并+单点更新+区间查询

    LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  7. hdu 1166 线段树 区间求和 +单点更新 CD模板

    题目链接 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total S ...

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

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

  9. HDU 1556 Color the ball(线段树区间更新)

    Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...

随机推荐

  1. CRM 客户关系管理系统

    CRM(Customer Relationship Manager)客户关系管理系统 企业为提高核心竞争力,利用相应的信息技术以及互联网技术协调企业与顾客间在销售.营销和服务上的交互,从而提升其管理方 ...

  2. 3、jquery_动态创建元素

    动态创建元素:$('<b>javier</b>') $('#Button1').append($('<b>javier</b>')) 等价于  $($( ...

  3. Beta冲刺测试

    1.项目概述 1.项目名称 微信四则运算小程序 2.项目简介 基于微信小程序,为用户提供一个答题的平台 3.项目预期达到目标 用户通过微信小程序可以在里边答题,模式或者题量的选择为用户匹配到适合他们的 ...

  4. InfoQ —— 腾讯游戏大数据服务场景与应用

    简介 周东祥,本人从2010年毕业进入腾讯互动娱乐部门工作,一直致力在腾讯游戏运营开发工作.先后负责SAP业务受理系统,盗号自助系统,元数据系统以及近2年在腾讯游戏大数据运营开发中积累大量的大数据开发 ...

  5. MCP|LQD|Data-independent acquisition improves quantitative cross-linking mass spectrometry (DIA方法可提升交联质谱定量分析)

    文献名:Data-independent acquisition improves quantitative cross-linking mass spectrometry (DIA方法可提升定量交联 ...

  6. dbms_xplan的display_cursor查看执行计划

    准备工作: SQL> conn sys/root as sysdba Connected. SQL> grant select on v_$sql_plan to scott; Grant ...

  7. ORM(一)

    ORM常识: 1.一对多,多的一方设置外键字段,有外键字段的表叫做子表.没有外键字段的表叫做主表. 2.主表放到子表的下面,否则子表找不到主表,写数据要先往主表中写. 数据库:(1)不创建主键,会自动 ...

  8. python绘制世界人口地图

    最近看了<python编程:从入门到实践>,里边设计的项目拿来学习学习,绘制世界人口地图. 首先,下载数据,http://data.okfn.org/ ,从这里下载population_d ...

  9. nginx大量TIME_WAIT的解决办法

    1.netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 查看time_wait 很大 2.解决此问题需要对sysc ...

  10. POJ 3537 Crosses and Crosses(sg博弈)

    题目:在1*n 的棋盘里面,A和B都在里面画叉 , 如果谁可以画了一个叉后,可以连成3个叉,那谁胜利 : 分析: 首先考虑如果我在玩游戏,我最希望对手可以画出-x-x or  -xx-   ,  这种 ...