毁灭者问题

题目及解题代码存于此处以便研读

  

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

在 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

AC的代码

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <iostream>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <map>
  8 #include <set>
  9 #include <queue>
 10 #include <bitset>
 11 #include <string>
 12 #define PQ priority_queue
 13 #define OO 2147483647
 14 #define Max(a, b) ((FASTBUFFER = ((a) - (b)) >> 31), ((b) & FASTBUFFER | (a) & ~FASTBUFFER))
 15 #define Min(a, b) ((FASTBUFFER = ((a) - (b)) >> 31), ((a) & FASTBUFFER | (b) & ~FASTBUFFER))
 16 #define Swap(a, b) (a ^= b, b ^= a, a ^= b)
 17
 18 using namespace std;
 19
 20 const int N = 100005;
 21
 22 typedef long long ll;
 23
 24 inline int ran() {
 25     static int x = 1;
 26     x += (x << 1) + 1;
 27     return x & 2147483647;
 28 }
 29
 30 struct Node;
 31
 32 typedef pair <Node*, Node*> Pair;
 33
 34 Node *null;
 35
 36 struct Node {
 37     int val, snow, size;
 38     ll sum;
 39     Node *left, *right;
 40
 41     Node (int val, int snow, Node *left, Node *right) :
 42     val(val), snow(snow), size(snow), left(left), right(right), sum((ll)val * snow) {}
 43
 44     Node *Update() {
 45         size = left->size + snow + right->size;
 46         sum = left->sum + (ll)val * snow + right->sum;
 47         return this;
 48     }
 49
 50     Pair split(int v);
 51 };
 52
 53 Node *Merge(Node *a, Node *b) {
 54     if (a == null) {
 55         return b;
 56     }
 57
 58     if (b == null) {
 59         return a;
 60     }
 61
 62     if (ran() % (a->size + b->size) < a->size) {
 63         a->right = Merge(a->right, b);
 64         return a->Update();
 65     }
 66
 67     b->left = Merge(a, b->left);
 68     return b->Update();
 69 }
 70
 71 Pair Node :: split(int v) {
 72     if (this == null) {
 73         return make_pair(null, null);
 74     }
 75
 76     if (val >= v) {
 77         Pair ret = left->split(v);
 78         left = ret.second;
 79         return make_pair(ret.first, this->Update());
 80     }
 81
 82     Pair ret = right->split(v);
 83     right = ret.first;
 84     return make_pair(this->Update(), ret.second);
 85 }
 86
 87 Node *root;
 88
 89 struct monsterNode {
 90     int s, m, r;
 91 }a[N];
 92
 93 int n, m;
 94 ll ans;
 95 multiset <int> s;
 96 vector <int> listInsert[N], listErase[N];
 97
 98 void insertWithTreap(int v) {
 99     Pair ret1 = root->split(v), ret2 = ret1.second->split(v + 1);
100     if (ret2.first->size) {
101         ret2.first->snow++;
102         ret2.first->size++;
103         ret2.first->sum += ret2.first->val;
104         root = Merge(ret1.first, Merge(ret2.first, ret2.second));
105         return;
106     }
107
108     root = Merge(ret1.first, Merge(new Node(v, 1, null, null), ret2.second));
109 }
110
111 void eraseWithTreap(int v) {
112     Pair ret1 = root->split(v), ret2 = ret1.second->split(v + 1);
113     if (ret2.first->size > 1) {
114         ret2.first->snow--;
115         ret2.first->size--;
116         ret2.first->sum -= ret2.first->val;
117         root = Merge(ret1.first, Merge(ret2.first, ret2.second));
118         return;
119     }
120
121     root = Merge(ret1.first, ret2.second);
122 }
123
124 void insertQuery(int t) {
125     multiset <int> :: iterator it1 = s.lower_bound(t), it2 = s.upper_bound(t);
126     if (*it1 == t) {
127         s.insert(t);
128         return;
129     }
130
131     if (it1 != s.begin()) {
132         it1--;
133     } else {
134         it1 = s.end();
135     }
136
137     if (it1 != s.end() && it2 != s.end()) {
138         eraseWithTreap(*it2 - *it1);
139     }
140
141     if (it1 != s.end()) {
142         insertWithTreap(t - *it1);
143     }
144
145     if (it2 != s.end()) {
146         insertWithTreap(*it2 - t);
147     }
148
149     s.insert(t);
150 }
151
152 void eraseQuery(int t)
153 {
154     s.erase(s.find(t));
155     multiset <int> :: iterator it1 = s.lower_bound(t), it2 = s.upper_bound(t);
156     if (*it1 == t) {
157         return;
158     }
159
160     if (it1 != s.begin()) {
161         it1--;
162     } else {
163         it1 = s.end();
164     }
165
166     if (it1 != s.end() && it2 != s.end()) {
167         insertWithTreap(*it2 - *it1);
168     }
169
170     if (it1 != s.end()) {
171         eraseWithTreap(t - *it1);
172     }
173
174     if (it2 != s.end()) {
175         eraseWithTreap(*it2 - t);
176     }
177 }
178
179 void askQuery(int start, int m, int r)
180 {
181     if (s.empty())
182         return;
183     ans += min((ll)(*s.begin()) * r + start, (ll)m);
184     if (r == 0) {
185         return;
186     }
187
188     int full = m / r + ((m % r) > 0);
189     Pair ret = root->split(full);
190     ans += (ll)m * ret.second->size;
191     ans += ret.first->sum * r;
192     root = Merge(ret.first, ret.second);
193 }
194
195 int main() {
196     null = new Node(0, 0, null, null);
197     root = null;
198     scanf("%d", &n);
199     for (int i = 1; i <= n; i++) {
200         scanf("%d %d %d", &a[i].s, &a[i].m, &a[i].r);
201     }
202
203     scanf("%d", &m);
204     for (int i = 1; i <= m; i++) {
205         int t, l, r;
206         scanf("%d %d %d", &t, &l, &r);
207         listInsert[l].push_back(t);
208         listErase[r].push_back(t);
209     }
210
211     for (int i = 1; i <= n; i++) {
212         for (int j = 0; j < listInsert[i].size(); j++) {
213             insertQuery(listInsert[i][j]);
214         }
215
216         askQuery(a[i].s, a[i].m, a[i].r);
217         for (int j = 0; j < listErase[i].size(); j++) {
218             eraseQuery(listErase[i][j]);
219         }
220     }
221
222     cout << ans << endl;
223     return 0;
224 }

时间: 2024-12-09 19:46:39

毁灭者问题的相关文章

hihocoder #1034 毁灭者问题

传送门 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在 Warcraft III 之冰封王座中,毁灭者是不死族打三本后期时的一个魔法飞行单位. 毁灭者的核心技能之一,叫做魔法吸收(Absorb Mana): 现在让我们来考虑下面的问题: 假设你拥有 n 个魔法单位,他们从左到有站在一行,编号从 1 到 n. 每个单位拥有三项属性: si: 初始法力. mi: 最大法力上限. ri: 每秒中法力回复速度. 现在你操纵一个毁灭者,有 m 个操作,t l r,表示时刻

hiho 毁灭者问题

描述 在 Warcraft III 之冰封王座中,毁灭者是不死族打三本后期时的一个魔法飞行单位. 毁灭者的核心技能之一,叫做魔法吸收(Absorb Mana): 现在让我们来考虑下面的问题: 假设你拥有 n 个魔法单位,他们从左到有站在一行,编号从 1 到 n. 每个单位拥有三项属性: si: 初始法力. mi: 最大法力上限. ri: 每秒中法力回复速度. 现在你操纵一个毁灭者,有 m 个操作,t l r,表示时刻 t,毁灭者对所有编号从 l 到 r 的单位,使用了魔法吸收.操作按照时间顺序给

读《三体Ⅲ &#183; 死神永生》| 只有仁慈没有能力,也不过是个毁灭者

从剧情的支线数量和时间顺序来讲,第三部要比第二部更友善一些.它有一个女主角作为主线,让人能比较轻松地在脑海里构建整个故事脉络,且支线不多,不用记那么多上一次的断点:此外,在书序之后,有一页纪年对照表,这一页极其重要,因为这一部横跨了多个时间段,在阅读时很容易混淆了事件发生的时刻位置,它提供了一个简单的时间索引.我常常在读的时候翻回这一页对照. 纪年对照表 危机纪元 公元201X年—2208年 威慑纪元 公元2208年—2270年 威慑后 公元2270年—2272年 广播纪元 公元2272年—23

【网易官方】极客战记(codecombat)攻略-森林-野餐毁灭者

关卡连接:https://codecombat.163.com/play/level/picnic-buster 免费试玩:https://codecombat.163.com/play 从巡逻的食人魔手中保护野餐者. 简介 使用 if 语句保护露营的人们,在食人魔进攻时挺身而出. if 语句对程序员来说至关重要,它们看起来像这样: enemy = hero.findNearestEnemy() if enemy: hero.attack(enemy) 默认代码 # 记得敌人可能还不存在. wh

hihoCoder挑战赛1 毁灭者问题

题目链接:http://hihocoder.com/problemset/problem/1034 数据结构题,由于每个魔法单位有着不同的回复速度和上限,所以不能根据吸收时间点进行查询和更新.但是如果知道每个人在哪些时间点被吸收了,那么可以按照每个单位的情况更新,具体操作是:时间间隔超过Mi/Ri的则被吸收的值为Mi(设这样的间隔有x个),否则为Ri*时间间隔(设这样的间隔总时间长度为y),此魔法单位被吸收的总量为x*Mi+y*Ri. 如何快速求每个单位在哪些时间被吸收:维护一个有序序列记录时间

PM2源码浅析

PM2工作原理 最近在玩一个游戏,<地平线:黎明时分>,最终Boss是一名叫黑底斯的人,所谓为人,也许不对,黑底斯是一段强大的毁灭进程,破坏了盖娅主进程,从而引发的整个大陆机械兽劣化故事. 为什么要讲这么一段呢,是希望大家可以更好地理解pm2的原理,要理解pm2就要理解god和santan的关系,god和santan的关系就相当于盖娅和黑底斯在pm2中的01世界中,每一行代码每一个字节都安静的工作god就是Daemon进程 守护进程,重启进程,守护node程序世界的安宁,santan就是进程的

黯淡蓝点:旅行者号64亿公里外回望地球...

1990年“旅行者”号探测器在即将飞出太阳系的时候,最后一次回眸我们的家园--地球! “旅行者”号探测器从40亿英里(约64亿公里)之外拍摄了上面两张地球照片.第一张照片中,地球仅是一个0.12个像素大小的圆点.著名天文学家卡尔·萨根将其描绘成“硕大的宇宙夜幕中一个孤独的圆点,对我来说,它强调了我们在更友善.更积极地处理相互之间的关系上的责任,以及保护和爱惜这个黯淡蓝点的责任,这是人类已知的唯一家园.” 地球是在这个浩翰宇宙剧院里的一个细小舞台. 想想从那些将令们和皇帝们溢出的血河,他们的光荣与

【随笔】长久以来关于电脑静音的一点心得

长期以来,一直被电脑机箱内的噪音困扰,相信很多朋友都有这样的困扰.同时,品牌机箱往往噪音就控制的很好,这让我相信,机箱降噪必然是可能的.于是,从大学时期的第一台电脑开始,就一直想尽办法的打造一台静音的电脑.办法用了很多,却一再受挫,知道我现在的电脑才真正实现了我的梦想.下面整理一下我的经验.======================我是罗嗦的分割线======================一.噪音来源分析知道了噪音来源才能有效的降低噪音.通过耳听.手摸等原始手段,使我认识到,计算机硬件上的电

《周鸿祎自述:我的互联网方法论》之精华笔记和思考

1. 用户不会在乎你的七大功能,八大特色,只要有一个功能可以打动他,可以解决它心中的痛,或者挠去他心中的痒,那你就有可能获得用户的信赖. 2. 不要给用户谈你们公司有多少个院士,多少个千人计划,多少个专家,多少个博士,你们的产品用到了多fancy的技术,大部分人不会care的. 最显然的就是这种科技新闻下的评论数量几乎为0. 3. 你做了一个新产品,然后你给用户说我用到了最高精尖的Deep Learning技术,通过利用人工神经网络模拟人脑神经的层次化结构实现更加高效精准识别,他们才不会在乎.