1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
struct SegmentTree {
int n;
vector<long long> tree;
vector<long long> lazy;
SegmentTree() : n(0) {}
SegmentTree(int n_, const vector<long long>& base) { init(n_, base); }
void init(int n_, const vector<long long>& base) {
n = n_;
tree.assign(4 * n + 4, 0);
lazy.assign(4 * n + 4, 0);
build(1, 1, n, base);
}
void build(int node, int l, int r, const vector<long long>& base) {
if (l == r) {
tree[node] = base[l];
return;
}
int mid = (l + r) >> 1;
build(node << 1, l, mid, base);
build(node << 1 | 1, mid + 1, r, base);
tree[node] = min(tree[node << 1], tree[node << 1 | 1]);
}
inline void apply(int node, long long val) {
tree[node] += val;
lazy[node] += val;
}
inline void push(int node) {
if (lazy[node] != 0) {
apply(node << 1, lazy[node]);
apply(node << 1 | 1, lazy[node]);
lazy[node] = 0;
}
}
void range_add(int L, int R, long long val) { range_add(1, 1, n, L, R, val); }
void range_add(int node, int l, int r, int L, int R, long long val) {
if (R < l || r < L) return;
if (L <= l && r <= R) { apply(node, val); return; }
push(node);
int mid = (l + r) >> 1;
range_add(node << 1, l, mid, L, R, val);
range_add(node << 1 | 1, mid + 1, r, L, R, val);
tree[node] = min(tree[node << 1], tree[node << 1 | 1]);
}
long long query_min(int L, int R) { return query_min(1, 1, n, L, R); }
long long query_min(int node, int l, int r, int L, int R) {
if (R < l || r < L) return LLONG_MAX / 4;
if (L <= l && r <= R) return tree[node];
push(node);
int mid = (l + r) >> 1;
return min(query_min(node << 1, l, mid, L, R),
query_min(node << 1 | 1, mid + 1, r, L, R));
}
};
struct Event {
char type; // '+', '-', '?'
long long t{0}, d{0}; // for '+': t, d; for '?': t
int ref{-1}; // for '-': referenced join index (0-based)
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int q; if (!(cin >> q)) return 0;
vector<Event> events(q);
vector<long long> all_times; all_times.reserve(q * 2);
for (int i = 0; i < q; ++i) {
char c; cin >> c; events[i].type = c;
if (c == '+') {
long long t, d; cin >> t >> d;
events[i].t = t; events[i].d = d;
all_times.push_back(t);
} else if (c == '-') {
int idx; cin >> idx; events[i].ref = idx - 1; // 0-based
} else { // '?'
long long t; cin >> t; events[i].t = t; all_times.push_back(t);
}
}
sort(all_times.begin(), all_times.end());
all_times.erase(unique(all_times.begin(), all_times.end()), all_times.end());
int m = (int)all_times.size();
auto get_index = [&](long long t) -> int {
return int(lower_bound(all_times.begin(), all_times.end(), t) - all_times.begin()) + 1; // 1-based
};
// Base arrays: initially P=0 → F[i] = -c_i, G[i] = -c_i
vector<long long> baseF(m + 1, 0), baseG(m + 1, 0);
for (int i = 1; i <= m; ++i) {
baseF[i] = -all_times[i - 1];
baseG[i] = -all_times[i - 1];
}
SegmentTree segF(m, baseF);
SegmentTree segG(m, baseG);
vector<int> join_pos(q, -1);
vector<long long> join_d(q, 0);
vector<char> is_active(q, 0);
for (int i = 0; i < q; ++i) {
if (events[i].type == '+') {
int pos = get_index(events[i].t);
long long d = events[i].d;
is_active[i] = 1; join_pos[i] = pos; join_d[i] = d;
// suffix add: all future times see increased P
segF.range_add(pos, m, d);
segG.range_add(pos, m, d);
// at exact arrival instant, consider value just-before-arrival
segG.range_add(pos, pos, -d);
} else if (events[i].type == '-') {
int j = events[i].ref;
if (j >= 0 && is_active[j]) {
int pos = join_pos[j]; long long d = join_d[j];
is_active[j] = 0;
segF.range_add(pos, m, -d);
segG.range_add(pos, m, -d);
segG.range_add(pos, pos, +d);
}
} else { // '?'
int pos = get_index(events[i].t);
long long Fpos = segF.query_min(pos, pos); // P(t) - t
long long minG = segG.query_min(1, pos); // min_{u≤t}(P(u)-u) 후보
long long mval = min(0LL, minG); // 공백 구간 허용
long long wait = Fpos - mval; // 백로그
cout << wait << '\n';
}
}
return 0;
}
|