HDU 3954 Level up(多颗线段树+lazy操作)
又是一开始觉得的水题,结果GG了好久的东西。。。
题意是给你n个英雄,每个英雄开始为1级经验为0,最多可以升到k级并且经验一直叠加,每一级都有一个经验值上限,达到就升级。接着给你两种操作:
W li ri ei:从第li到第ri个增加经验基数ei,注意这儿ei还需要乘以级数才是真正增加的经验,还有就是先在此等级下增加此等级倍数的经验,然后再判断升级情况
Q li ri :在第li到第ri个查找经验最多的值
记录最大值嘛,不过因为级数控制增加的倍数,也就是说区间更新时,多次更新标记得到的只是基数ei,倍数不确定。所以可以从级数k(小于11)入手,建立10棵线段树每个等级一颗,然后没有这个等级就记为-1,有就记录最大经验值。但是还有一个问题就是此点代表的区间有些人升级,有些人没升级,所以我们把每个会升级的节点都更新到底(每个节点最大经验值就在于判断这一段是否有人升级),最多就k*n次。最后要注意一个问题,就是当增加ei的时候,可能不止升一级。
这儿牵扯到lazy操作的修改模板(其实我的模板虽然基本一样,但是我还是经常会改变写法的)
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=<<;
const double Pi=acos(-1.0);
const int Max=<<;
int segtr[][Max],upn[Max];//分别记录十个等级的最大值,意为建立10棵树
int lev[];//k比较小,则可以开数组记录每一等级的最大经验值 以此来看是否有人升级 有人升级就更新到叶子节点 最大等级k比较小所以不会超时
int nmax(int a,int b)
{
return a>b?a:b;
}
void Upnow(int now,int next,int k)//上更新 关键
{
for(int i=; i<k; i++)
segtr[i][now]=nmax(segtr[i][next],segtr[i][next|]);
return;
}
void Create(int sta,int enn,int now,int k)
{
upn[now]=;
segtr[][now]=;
for(int i=; i<k; i++)//这一段没有这个等级
segtr[i][now]=-;
if(sta==enn)
return;
int mid=dir(sta+enn,);
int next=mul(now,);
Create(sta,mid,next,k);
Create(mid+,enn,next|,k);
return;
}
int Levup(int i,int now,int k,int z)//判断升级函数
{
int j,flag=;
if(segtr[i][now]!=-)
{
segtr[i][now]+=(i+)*z;
j=i;
while(segtr[j][now]>=lev[j])//可能不止升一级
{
segtr[j+][now]=nmax(segtr[j+][now],segtr[j][now]);
j++;
}
if(segtr[i][now]>=lev[i])
{
segtr[i][now]=-;//一定更新到叶子,所以直接赋值为-1,**过后一定会回溯更新父节点**
flag=;
}
}
return flag;
}
void Downow(int now,int next,int k)//lazy更新
{
if(upn[now])
{
upn[next]+=upn[now];
upn[next|]+=upn[now];
for(int i=k-; i>=; i--)
{
Levup(i,next,k,upn[now]);//每个孩子节点的10个值要处理lazy操作
Levup(i,next|,k,upn[now]);
}
upn[now]=;
}
return;
}
int Update(int sta,int enn,int now,int x,int y,int z,int k)
{
if(sta>=x&&enn<=y)
{
int flag=;
for(int i=k-; i>=; i--)
flag|=Levup(i,now,k,z);//升级了就一定继续更新,不返回
if(!flag||sta==enn)//没人升级或者已经更新到叶子节点
{
int manx=;
for(int i=; i<k; i++)
manx=nmax(manx,segtr[i][now]);
upn[now]+=z;
return manx;
}
}
int mid=dir(sta+enn,);
int next=mul(now,);
Downow(now,next,k);
int ans=;
if(mid>=x)//这儿有时可以做文章
ans=nmax(ans,Update(sta,mid,next,x,y,z,k));
if(mid<y)
ans=nmax(ans,Update(mid+,enn,next|,x,y,z,k));
Upnow(now,next,k);
return ans;
}
int main()
{
int t,n,k,q,coun=;
int lef,rig,ei;
char str[];
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d",&n,&k,&q);
for(int i=; i<k-; i++)
scanf("%d",&lev[i]);
lev[k-]=Inf;//不能再升级
Create(,n,,k);
printf("Case %d:\n",++coun);
for(int i=; i<q; i++)
{
scanf("%s",str);
if(str[]=='W')
{
scanf("%d %d %d",&lef,&rig,&ei);
Update(,n,,lef,rig,ei,k);
}
else
{
scanf("%d %d",&lef,&rig);
printf("%d\n",Update(,n,,lef,rig,,k));
}
}
printf("\n");
}
return ;
}
HDU 3954 Level up(多颗线段树+lazy操作)的更多相关文章
- hdu 1698 Just a Hook 【线段树+lazy】
题目 写了一天的线段树,这道题主要说明一下sum是赋值的,不是累加的,并且在push_down的时候lazy也是赋值的.因可能对懒标记的理解还不是很透彻吧. #include <iostream ...
- poj 3237 树链剖分模板(用到线段树lazy操作)
/* 本体在spoj375的基础上加了一些操作,用到线段树的lazy操作模板类型 */ #include<stdio.h> #include<string.h> #includ ...
- POJ3468【线段树lazy操作】
上午理论AC,打到现在快吐了... 一个那么**Lazy操作打成这样,query操作和update操作都有问题,妈蛋,发现是mid<=s+1-真是蠢到家,明明是mid+1<=s卧槽连左和右 ...
- hdoj1698【线段树Lazy操作】
区间更新lazy操作一发. #include<cstdio> #include<iostream> #include<string.h> #include<a ...
- hdu 3954 Level up(线段树)
题目链接:hdu 3954 Level up 题目大意:N个英雄,M个等级,初始等级为1,给定每一个等级须要的经验值,Q次操作,操作分两种,W l r x:表示l~r之间的英雄每一个人杀了x个怪物:Q ...
- HDU 3954 Level up(线段树)
HDU 3954 Level up 题目链接 题意:k个等级,n个英雄,每一个等级升级有一定经验,每次两种操作,一个区间加上val,这样区间内英雄都获得当前等级*val的经验,还有一个操作询问区间经验 ...
- HDU 4267 A Simple Problem with Integers(2012年长春网络赛A 多颗线段树+单点查询)
以前似乎做过类似的不过当时完全不会.现在看到就有点思路了,开始还有洋洋得意得觉得自己有不小的进步了,结果思路错了...改了很久后测试数据过了还果断爆空间... 给你一串数字A,然后是两种操作: &qu ...
- hdu 5274 Dylans loves tree(LCA + 线段树)
Dylans loves tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- hdu 2871 线段树(各种操作)
Memory Control Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
随机推荐
- mysql的UNIX_TIMESTAMP用法
UNIX_TIMESTAMP 一般是用于unix的时间戳. 例子: SELECT UNIX_TIMESTAMP("2016-07-11")-- 1468166400SELECT U ...
- 使用React的static方法实现同构以及同构的常见问题
代码地址请在github查看,假设有新内容.我会定时更新.也欢迎您star,issue,共同进步 1.我们服务端渲染数据从何而来 1.1 怎样写出同构的组件 服务端生成HTML结构有时候并不完好.有时 ...
- shiro集成encache
针对多频次或者几乎不变的大数量的数据,我们可以通过缓存来实现,具体的比如说权限认证,这个,每次操作都需要权限认证,所以,这里添加encache注解.具体的认证过程是: 1,用户第一次访问用户权限信息, ...
- android Notification 的使用(锁定通知栏)
近期一直在研究 android .并一边研究一边做应用.当中遇到了把程序通知常驻在 Notification 栏,而且不能被 clear 掉(就像android QQ一样)的问题.经过研究实现了其功能 ...
- shell遍历文件目录,监听文件变化,拼接字符串
最近利用业余时间学习了shell 并做了个例子 实现的功能是 : 监听demo文件夹下的文件,只要新增了 .js的文件就把对应的文件名重组,拼接, 最后写入到demo.js里面. 文件结构如下 : ...
- C语言中的指针运算
int a[5]={1,2,3 ,4,5} *p=a; *p++ 等价于*(p++) 等价于a[i++](i++ i首先会被使用任何进行自+) *++p等价于*(++p) 等价于 a[++i] (++ ...
- 串 2016Vijos省选集训 day3[AC自动机]
1.串(string.c/.cpp/.pas) 限时1s,内存限制256MB,20个测试点 [题目描述] 兔子们在玩字符串的游戏.首先,它们拿出了一个字符串集合S,然后它们定义一个字符串为“好”的,当 ...
- java jdk和android sdk的安装以及环境变量的配置
安卓环境变量设置 (烦)http://wenku.baidu.com/link?url=QRwpFhP8d0yJorhcvuZPrz3lNFQW-uwYg6TlZtv6uen6_SVsvRrzf0UJ ...
- iOS源代码管理svn
01. SVN介绍 SVN 是集中式源代码管理工具 概念: 1> Repository 代码仓库,保存代码的仓库 2> Server 服务器,保存所有版本的代码仓库 3&g ...
- Netty环境搭建 (源码死磕2)
[正文]netty源码 死磕2: 环境搭建 本小节目录 1. Netty为什么火得屌炸天? 1.1. Netty是什么? 1.2. Netty火到什么程度呢? 1.3. Netty为什么这么火? 2 ...