传送门

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

在 Warcraft III 之冰封王座中,毁灭者是不死族打三本后期时的一个魔法飞行单位。

毁灭者的核心技能之一,叫做魔法吸收(Absorb Mana):

现在让我们来考虑下面的问题:

假设你拥有 n 个魔法单位,他们从左到有站在一行,编号从 1 到 n。 每个单位拥有三项属性:

  • si: 初始法力。

  • mi: 最大法力上限。

  • ri: 每秒中法力回复速度。

现在你操纵一个毁灭者,有 m 个操作,t l r,表示时刻 t,毁灭者对所有编号从 lr 的单位,使用了魔法吸收。操作按照时间顺序给出,计算毁灭者一共吸收了多少法力。

输入

输入数据的第一行有一个整数 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 毁灭者问题的更多相关文章

  1. hihocoder #1034 : 毁灭者问题 平衡树(set)+线段树

    #1034 : 毁灭者问题 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在 Warcraft III 之冰封王座中,毁灭者是不死族打三本后期时的一个魔法飞行单位. 毁 ...

  2. hihoCoder Challenge 1

    #1034 : 毁灭者问题 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在 Warcraft III 之冰封王座中,毁灭者是不死族打三本后期时的一个魔法飞行单位. 毁 ...

  3. hihoCoder挑战赛1 毁灭者问题

    题目链接:http://hihocoder.com/problemset/problem/1034 数据结构题,由于每个魔法单位有着不同的回复速度和上限,所以不能根据吸收时间点进行查询和更新.但是如果 ...

  4. hihocoder -1121-二分图的判定

    hihocoder -1121-二分图的判定 1121 : 二分图一•二分图判定 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 大家好,我是小Hi和小Ho的小伙伴Net ...

  5. Hihocoder 太阁最新面经算法竞赛18

    Hihocoder 太阁最新面经算法竞赛18 source: https://hihocoder.com/contest/hihointerview27/problems 题目1 : Big Plus ...

  6. hihoCoder太阁最新面经算法竞赛15

    hihoCoder太阁最新面经算法竞赛15 Link: http://hihocoder.com/contest/hihointerview24 题目1 : Boarding Passes 时间限制: ...

  7. 【hihoCoder 1454】【hiho挑战赛25】【坑】Rikka with Tree II

    http://hihocoder.com/problemset/problem/1454 调了好长时间,谜之WA... 等我以后学好dp再来看为什么吧,先弃坑(╯‵□′)╯︵┻━┻ #include& ...

  8. 【hihocoder#1413】Rikka with String 后缀自动机 + 差分

    搞了一上午+接近一下午这个题,然后被屠了个稀烂,默默仰慕一晚上学会SAM的以及半天4道SAM的hxy大爷. 题目链接:http://hihocoder.com/problemset/problem/1 ...

  9. 【hihoCoder】1148:2月29日

    问题:http://hihocoder.com/problemset/problem/1148 给定两个日期,计算这两个日期之间有多少个2月29日(包括起始日期). 思路: 1. 将问题转换成求两个日 ...

随机推荐

  1. js中的return,return true,return false小结

    return  函数执行到这句时会终结,并返回调用函数,而且把表达式的值作为函数的结果返回 return false 可以防止默认的事件行为.例如,默认情况下点击一个<a>元素,页面会跳转 ...

  2. ruby on rails 里使用SideKiq 做后台任务

    环境:ubuntu14.4,ruby2.1.5, rails4.2 一.新一个rais项目:rails new active_job --skip-bundle       进入项目文件夹: cd a ...

  3. Download the WDK, WinDbg, and associated tools

    Download the WDK, WinDbg, and associated tools This is where you get your Windows Driver Kit (WDK) a ...

  4. raid知识

    1,raid形象理解(饮水机模型) http://dingyichao.blog.51cto.com/442449/698762     2,raid利用率 3,raid详细理解 raid0 raid ...

  5. Web API路由和动作选择

    前言 本文描述ASP.NET Web API如何把一个HTTP请求路由到控制器的一个特定的Action上.关于路由的总体概述可以参见上一篇教程 http://www.cnblogs.com/aehyo ...

  6. 如何拿到半数面试公司Offer——我的Python求职之路(转)

    原文出处:http://www.cnblogs.com/Lands-ljk/p/5836492.html 从八月底开始找工作,短短的一星期多一些,面试了9家公司,拿到5份Offer,可能是因为我所面试 ...

  7. Linux常用指令---tar | zip (解压缩)

    减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间.gzip是在Linux系统中经常使用的一个对文件进行压缩和解压缩的命令,既方便又好用.gzip不仅可以用 ...

  8. 8.HBase In Action 第一章-HBase简介(1.2.2 捕获增量数据)

    Data often trickles in and is added to an existing data store for further usage, such as analytics, ...

  9. 整理sqlserver 级联更新和删除 c#调用存储过程返回值

    整理一下级联更新和删除 c#调用返回值 use master go IF exists(select 1 from sysdatabases where name='temp') BEGIN DROP ...

  10. 『设计』Slithice 分布式架构设计-支持一体式开发,分布式发布

    项目原因: 参与过各种 分布式项目,有 Socket,Remoting,WCF,当然还有最常用的可以跨平台的 WebService. 分布式编码的时间浪费: 但是,无一例外的,开发分布式程序的开发遵循 ...