# P11728 [集训队互测 2015] Robot
## 题目描述
小 q 有 $n$ 只机器人,一开始他把机器人放在了一条数轴上,第 $i$ 只机器人在 $a_i$ 的位置上静止,而自己站在原点。
在这之后小 q 会执行一些操作,他想要命令一个机器人向左或者向右移动 $x$ 格。但是机器人似乎听不清小 q 的命令,事实上它们会以每秒 $x$ 格的速度匀速移动。
看着自己的机器人越走越远,小 q 很着急,他想知道当前离他(原点)最远的机器人有多远。
具体的操作以及询问见输入格式。注意,不同的机器人之间互不影响,即不用考虑两个机器人撞在了一起的情况。
## 输入格式
共有 $m$ 个事件,输入将会按事件的时间顺序给出。
第一行两个正整数 $n,m$。
接下来一行 $n$ 个整数,第 $i$ 个数是 $a_i$,表示第 $i$ 个机器人初始的位置(初始移动速度为 $0$)。
接下来 $m$ 行,每行行首是一个非负整数 $t_i$,表示该事件点发生的时刻(以秒为单位)。第二个是一个字符串 $S$ ,代表操作的种类。数字与字符串之间用一个空格隔开。接下来的输入按 $S$ 的种类分类。
1. 若 $S$ 是 `command`,则接下来两个整数 $k_i,x_i$,表示小 q 对第 $k_i$ 个机器人执行了操作,该机器人的速度将会被重置,变为向数轴正方向每秒移动 $x_i$ 格(若 $x_i$ 为负数就相当于向数轴负方向每秒移动 $\lvert x_i \rvert$ 格)。保证 $1 \leq k_i \leq n$。
2. 若 $S$ 是 `query`,则你需要输出当前离原点最远的机器人有多远。
保证 $t_1 \leq t_2 \leq t_2 \leq \dots \leq t_m$。
(注:若同一时间发生多次操作,则按读入顺序依次执行)
## 输出格式
对于每个 `query` 询问,输出一行,包含一个整数表示正确的答案。
**由于本题数据量较大,建议使用高效的的输入输出方式。**
## 输入输出样例 #1
### 输入 #1
```
4 5
-20 0 20 100
10 command 1 10
20 command 3 -10
30 query
40 command 1 -30
50 query
```
### 输出 #1
```
180
280
```
## 说明/提示
### 样例解释
- 第一个命令执行时,各个机器人的位置为:$-20, 0, 20, 100$。
- 第二个命令执行时,各个机器人的位置为:$80, 0, 20, 100$。
- 第一个询问时,各个机器人的位置为:$180, 0, -80, 100$。
- 第三个命令执行时,各个机器人的位置为:$280, 0, -180, 100$。
- 第二个询问时,各个机器人的位置为:$-20, 0, -280, 100$。
### 数据范围
设 `command` 的个数为 $C$,`query` 的个数为 $Q$。(所以 $C + Q = m$)
对于所有的事件满足 $0 \leq t_i \leq 10^9$,对于所有的 `command` 满足 $\lvert x_i \rvert \leq 10^4$。
对于所有的机器人满足 $\lvert a_i \rvert \leq 10^9$。
所有测试数据的范围和特点如下表所示:
| 测试点编号 | 数据范围 | 特殊限制 |
| :----------: | :----------: | :----------: |
| $1$ | $n,m\leq 2000$ | 无 |
| $2$ | $n,m\leq 2000$ | 无 |
| $3$ | $n,m\leq 10^5$ | $-1 \leq x_i \leq 1$ |
| $4$ | $n,C\leq 10^5$,$Q\leq 5\times 10^5$ | 两个机器人发生碰面或者超越另一个的次数 $\leq 4\times 10^5$ |
| $5$ | $n,C\leq 10^5$,$Q\leq 5\times 10^5$ | 两个机器人发生碰面或者超越另一个的次数 $\leq 4\times 10^5$ |
| $6$ | $n,m\leq 10^5$ | 不会在 $t_i>0$ 时出现 `command` 操作 |
| $7$ | $n,m\leq 10^5$ | 不会在 $t_i>0$ 时出现 `command` 操作 |
| $8$ | $n,m\leq 10^5$ | 无 |
| $9$ | $n,C\leq 10^5$,$Q\leq 5\times 10^5$ | 无 |
| $10$ | $n,C\leq 10^5$,$Q\leq 5\times 10^5$ | 无 |
为什么WA了
```cpp
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAX_N = 2e6;
int n, m, lst[MAX_N], id[MAX_N];
int t[MAX_N], k[MAX_N], x[MAX_N];
ll a[MAX_N];
struct Line {
ll k, b;
Line(ll k = 0, ll b = 0) : k(k), b(b) { }
} line[MAX_N];
inline ll get(int idx, int x) {
return line[idx].k * t[x] + line[idx].b;
}
int tr[MAX_N << 2];
#define ls(cur) cur << 1
#define rs(cur) cur << 1 | 1
void update(int cur, int l, int r, int idx) {
int mid = l + r >> 1;
if (get(tr[cur], mid) < get(idx, mid))
swap(tr[cur], idx);
if (l == r)
return ;
if (get(tr[cur], l) < get(idx, r))
update(ls(cur), l, mid, idx);
if (get(tr[cur], r) < get(idx, r))
update(rs(cur), mid + 1, r, idx);
}
void insert(int cur, int l, int r, int L, int R, int idx) {
if (L > r || l > R)
return ;
if (L <= l && r <= R) {
update(cur, l, r, idx);
return ;
}
int mid = l + r >> 1;
if (L <= mid)
insert(ls(cur), l, mid, L, R, idx);
if (mid + 1 <= R)
insert(rs(cur), mid + 1, r, L, R, idx);
}
ll query(int cur, int l, int r, int x) {
ll tmp = get(tr[cur], x);
if (l == r)
return tmp;
int mid = l + r >> 1;
if (x <= mid)
return max(tmp, query(ls(cur), l, mid, x));
else
return max(tmp, query(rs(cur), mid + 1, r, x));
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m;
int tot = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
line[++tot] = Line(0, a[i]);
lst[i] = 0, id[i] = tot;
}
for (int i = 1; i <= m; i++) {
string s;
cin >> t[i] >> s;
if (s[0] == 'c')
cin >> k[i] >> x[i];
}
for (int i = 1; i <= m; i++) {
if (!k[i])
continue;
insert(1, 0, m, lst[k[i]], i - 1, id[k[i]]);
line[++tot] = Line(-line[id[k[i]]].k, -line[id[k[i]]].b);
insert(1, 0, m, lst[k[i]], i - 1, tot);
a[k[i]] += 1ll * (t[i] - t[lst[k[i]]]) * x[lst[k[i]]];
// ll pos = line[id[k[i]]].b + 1ll * t[i] * x[lst[k[i]]]
line[++tot] = Line(x[i], a[k[i]] - 1ll * t[i] * x[i]);
lst[k[i]] = i, id[k[i]] = tot;
}
for (int i = 1; i <= n; i++) {
insert(1, 0, m, lst[i], m, id[i]);
line[++tot] = Line(-line[id[i]].k, -line[id[i]].b);
insert(1, 0, m, lst[i], m, tot);
}
for (int i = 1; i <= m; i++)
if (!k[i])
cout << query(1, 0, m, i) << '\n';
return 0;
}
```
最新发布