hihocoder #1034 毁灭者问题
描述
在 Warcraft III 之冰封王座中,毁灭者是不死族打三本后期时的一个魔法飞行单位。
毁灭者的核心技能之一,叫做魔法吸收(Absorb Mana):
现在让我们来考虑下面的问题:
假设你拥有 n 个魔法单位,他们从左到有站在一行,编号从 1 到 n。 每个单位拥有三项属性:
si: 初始法力。
mi: 最大法力上限。
ri: 每秒中法力回复速度。
现在你操纵一个毁灭者,有 m 个操作,t l r,表示时刻 t,毁灭者对所有编号从 l 到 r 的单位,使用了魔法吸收。操作按照时间顺序给出,计算毁灭者一共吸收了多少法力。
输入
输入数据的第一行有一个整数 n (1 ≤ n ≤105) — 你的魔法单位的数目。
接下来的 n 行,每行有三个整数 si, mi, ri (0 ≤ si ≤ mi ≤ 105, 0 ≤ ri ≤ 105) 描述一个魔法单位。
接下来一行又一个整数 m (1 ≤ m ≤ 105), — 操作的数目。
接下来的 m 行,每行描述一个操作 t, l, r(0 ≤ t ≤ 109, 1 ≤ l ≤ r ≤ n),t 非降。
输出
输出一行一个整数表示毁灭者一共吸收了多少法力。
- 样例输入
-
5
0 10 1
0 12 1
0 20 1
0 12 1
0 10 1
2
5 1 5
19 1 5 - 样例输出
-
83
Solution:
如果魔法单位没有法力上限,这道题就是一道水题了,线段树即可搞定。
设置了法力上限,从维护区间的角度来考虑就比较困难了。
我们换一种思路,考虑对每一个魔法单位维护其遭遇收割的各个时刻,或者说其遭遇收割的时间序列(以下简称“时间序列”)。
这样就可以轻松求出毁灭者在各个魔法单位收割的法力值,做法如下:
为简单计,先假设所有魔法单位的初始法力都为零。
设魔法单位 $i$ 法力回满所需时间为 $T$,显然 $T=\lceil \frac{m_i}{r_i}\rceil$ 。
考察相邻收割时刻 $t_k$与$t_{k+1}$,其间隔记做 $\Delta t=t_{k+1}-t_{k}$,若 $\Delta t<T$ 则$t_{k+1}$ 时刻收割的法力值为 $\Delta t\times r_i$,否则为 $m_{i}$ 。
对于每个魔法单位我们只要知道其遭遇收割的时间间隔(以下简称“时间间隔”)中,大于等于$T$的时间间隔的个数以及小于 $T$ 的时间间隔的总和。
对每个魔法单位,我们可以用 map 来维护其遭受收割的时间序列,用树状数组来维护时间间隔之和与时间间隔的数量之和。
对每个魔法单位都按上述方式做一遍,时间上不能承受。同时应当注意到相邻魔法单位的时间序列是有联系的,可以动态维护
假设现在已经维护好了第 $i$ 个魔法单位的时间序列和时间间隔,在此基础上去掉所有以 $i$ 为区间右端点的收割时刻,再插入所有以 $i+1$ 为区间左端点的收割时刻,就得到了第 $i+1$ 个魔法单位的时间序列。
删除一个时刻 $t_{i}$ 意味着删除了两个时间间隔 $t_{i}-t_{i-1}$ 和 $t_{i+1}-t_{i}$,新增了一个时间间隔 $t_{i+1}-t_{i-1}$;插入一个时刻 $t_{i}$ 的作用恰好相反。
Implementation:
对每个魔法单位,先维护出以其为左端点和右端点的收割操作。然后从左到右动态维护各个魔法单位的时间序列,同时记录下相应的时间间隔的插入与删除操作。
对涉及到的所有时间间隔进行离散化。然后对每个魔法单位,先将其对应的(或称“贡献的”)时间间隔的插入与删除操作更新到树状数组中。
最后查询两类时间间隔贡献的法力加到答案中。
另外还要考虑到初始法力值可能不为零,这并不会带来什么困难,只要算一下毁灭者在每个魔法单位第一次吸收的法力的实际值和假设初始法力为零的情况之差,加到答案里去。
复杂度 $O((m+n)\log m)$
#include <bits/stdc++.h>
using namespace std; const int N(1e5+);
typedef long long LL; LL bit[N<<];
int a[N], m[N], r[N], bit2[N<<];
vector<int> Lt[N], Rt[N], op[N], b;
map<int,int> s; void add(int x, int v, int n){
for(; x<=n; bit[x]+=v, x+=x&-x);
} LL sum(int x){
LL res=;
for(; x; res+=bit[x], x-=x&-x);
return res;
} void Add(int x, int v, int n){
for(; x<=n; bit2[x]+=v, x+=x&-x);
} int Sum(int x){
int res=;
for(; x; res+=bit2[x], x-=x&-x);
return res;
} int main(){
int n, q;
scanf("%d", &n);
for(int i=; i<=n; i++) scanf("%d%d%d", a+i, m+i, r+i);
scanf("%d", &q);
for(int l, r, t; q--; ){
cin>>t>>l>>r;
Lt[l].push_back(t);
Rt[r].push_back(t);
}
s[]++;
LL ans=;
for(int i=; i<=n; i++){
for(auto &t: Rt[i-]){
if(--s[t]) continue;
auto p=s.lower_bound(t);
int pre, suc;
pre=(--p)->first, ++p, op[i].push_back(pre-t);
if(++p!=s.end())
suc=p->first, op[i].push_back(t-suc), op[i].push_back(suc-pre), b.push_back(suc-pre);
s.erase(--p); //error-prone
}
for(auto &t: Lt[i]){
if(s[t]++) continue;
auto p=s.lower_bound(t);
int pre, suc;
pre=(--p)->first, ++p, op[i].push_back(t-pre), b.push_back(t-pre);
if(++p!=s.end()) suc=p->first, op[i].push_back(suc-t), b.push_back(suc-t), op[i].push_back(pre-suc);
}
if(s[]>) ans+=a[i];
else{
auto p=s.begin();
if(++p!=s.end()){
int t=p->first;
ans+=min(a[i]+(LL)t*r[i], (LL)m[i])-min((LL)t*r[i], (LL)m[i]); //error-prone
}
}
}
sort(b.begin(), b.end());
auto e=unique(b.begin(), b.end());
int size=e-b.begin();
for(int i=; i<=n; i++){
for(int &x: op[i]){
int id=upper_bound(b.begin(), e, abs(x))-b.begin(); //error-prone
add(id, x, size);
if(x<) Add(id, -, size);
else Add(id, , size);
}
if(m[i]== || r[i]==) continue; //error-prone
int t=(m[i]-)/r[i]+;
int id=lower_bound(b.begin(), e, t)-b.begin();
ans+=(LL)(Sum(size)-Sum(id))*m[i];
ans+=sum(id)*r[i];
}
printf("%lld\n", ans);
return ;
}
代码中坑主要有
(1)注意需要用long long的地方
(2)别忘了将时刻从map中删除(代码第52行)
s.erase(--p); //error-prone
对拍才发现跪在这里的,多么痛的领悟。。。静态查错很重要啊。。。。。。。。。。。
hihocoder #1034 毁灭者问题的更多相关文章
- hihocoder #1034 : 毁灭者问题 平衡树(set)+线段树
#1034 : 毁灭者问题 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在 Warcraft III 之冰封王座中,毁灭者是不死族打三本后期时的一个魔法飞行单位. 毁 ...
- hihoCoder Challenge 1
#1034 : 毁灭者问题 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在 Warcraft III 之冰封王座中,毁灭者是不死族打三本后期时的一个魔法飞行单位. 毁 ...
- hihoCoder挑战赛1 毁灭者问题
题目链接:http://hihocoder.com/problemset/problem/1034 数据结构题,由于每个魔法单位有着不同的回复速度和上限,所以不能根据吸收时间点进行查询和更新.但是如果 ...
- hihocoder -1121-二分图的判定
hihocoder -1121-二分图的判定 1121 : 二分图一•二分图判定 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 大家好,我是小Hi和小Ho的小伙伴Net ...
- Hihocoder 太阁最新面经算法竞赛18
Hihocoder 太阁最新面经算法竞赛18 source: https://hihocoder.com/contest/hihointerview27/problems 题目1 : Big Plus ...
- hihoCoder太阁最新面经算法竞赛15
hihoCoder太阁最新面经算法竞赛15 Link: http://hihocoder.com/contest/hihointerview24 题目1 : Boarding Passes 时间限制: ...
- 【hihoCoder 1454】【hiho挑战赛25】【坑】Rikka with Tree II
http://hihocoder.com/problemset/problem/1454 调了好长时间,谜之WA... 等我以后学好dp再来看为什么吧,先弃坑(╯‵□′)╯︵┻━┻ #include& ...
- 【hihocoder#1413】Rikka with String 后缀自动机 + 差分
搞了一上午+接近一下午这个题,然后被屠了个稀烂,默默仰慕一晚上学会SAM的以及半天4道SAM的hxy大爷. 题目链接:http://hihocoder.com/problemset/problem/1 ...
- 【hihoCoder】1148:2月29日
问题:http://hihocoder.com/problemset/problem/1148 给定两个日期,计算这两个日期之间有多少个2月29日(包括起始日期). 思路: 1. 将问题转换成求两个日 ...
随机推荐
- 第五章 使用 Bootstrap Typeahead 组件(百度下拉效果)
推荐链接:http://www.cnblogs.com/haogj/p/3376874.html UnderScore官网:http://underscorejs.org/ 参考文档:http://w ...
- [1]Telerik Extensions for ASP.NET MVC 中文教程(转)
http://demos.telerik.com/aspnet-mvc/ Telerik Extensions for ASP.NET MVC 是Telerik 公司专门针对Asp.net MVC 开 ...
- [应用层]mail邮件协议
转:http://***/chapter-14/ 以前老记不住这smtp和pop3谁收谁发. 简单邮件传输协议(SMTP),用来发送或中转发出的电子邮件,占用tcp 25端口. 第三版邮局协议(POP ...
- CAS 单点登录流程
经验:在网上学东西不要指望一篇文章就能让你明白——我在网上学CAS流程,看了五六篇博文,其中三篇是觉得作者表达能力不行,或者作者自己就没明白怎么回事就出来写东西,看到一半就跳过了,剩下两篇每篇看了两遍 ...
- C++ 栈的基本操作
// zhan.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> using namesp ...
- Table AdvanceTable针对表内行禁用multipleSelection , singleSelection
OATableBean table = (OATableBean)webBean.findChildRecursive("LineTable"); table.setInserta ...
- Android连接网络打印机,jSocket连接网络打印机
老大写的一个打印工具类,记录一下. package com.Ieasy.Tool; import android.annotation.SuppressLint; import java.io.IOE ...
- 《深入理解计算机系统》深入实践之——vim深入研究
vim 用户手册中,大部分的例子都是在讲 vim 如何高效编写代码,由此可见,vim 是一款面向于程序员的多功能编辑器,即使某些功能 vim 无法直接完成,借助其丰富的插件资源,必定可以达成目标,这就 ...
- Linux第14周学习笔记
虚拟存储器 虚拟存储器是硬件异常.硬件地址翻译.主存.磁盘文件和内核软件的完美交互. 虚拟存储器的特点: 中心的 强大的 危险的 物理和虚拟寻址 计算机系统的主存被组织成一个由M个连续的字节大小的单元 ...
- app整体搭建环境:tabBar切换不同控制器的封装(自定义导航+自定义uiviewcontroler+系统自带tabbar+自定义tabbarController)
首先,一个app的搭建环境非常重要.既要实现基本功能,又要考虑后期优化的性能. 现在很多应用不仅仅是系统自带的控制器,由于需求复杂,基本上需要自定义多控制器来管理. 新建一个BasicNavigati ...