题目链接:https://codeforces.com/contest/1089/problem/K
题意:
有一些骑士要去见国王,公主也要见国王
给你q个询问,询问有三种操作,
1、+ t d 表示一个骑士在t分钟的时候去见国王,要见d分钟。
2、 - i 表示取消输入序列的第i个想要见国王的骑士
3、? t 表示如果公主在 t 时间见国王,要等多久
国王每次只能见一个人,其他人要在外面等着,如果公主和一个骑士同时到达,那么公主等着。
根据时间轴来建立线段树,每个节点维护,①这个区间内需要国王处理的总时间sum,②这个区间内的骑士至少到哪个时间点才能都见完国王。
这样对于公主在t时间点到来,必有一个骑士在 i 时间点,i + sum[i][t] 是公主到的时间,
只要求从1-t之间 最晚 处理完所有的骑士的时间T,T-t 即公主等待的时间,如果T <= t 则公主不需要等待
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e6 + 10;
struct node{
int d, t;
}pos[maxn];
struct Tree{
int l, r;
ll sum, maxx;
}e[maxn << 2];
void pushup(int cur){
e[cur].sum = e[cur << 1].sum + e[cur << 1 | 1].sum;
e[cur].maxx = max(e[cur << 1 | 1].maxx, e[cur << 1].maxx + e[cur << 1 | 1].sum);
}
void build(int l, int r, int cur){
e[cur].l = l;
e[cur].r = r;
e[cur].sum = 0;
e[cur].maxx = 0;
if(l == r) {
e[cur].maxx = l;
return ;
}
int mid = l + r >> 1;
build(l, mid, cur << 1);
build(mid + 1, r, cur << 1 | 1);
pushup(cur);
}
void update(int l, int r, int cur, int pos, int val){
if(l == r){
e[cur].maxx += val;
e[cur].sum += val;
return;
}
int mid = l + r >> 1;
if(pos <= mid) update(l, mid, cur << 1, pos, val);
else update(mid + 1, r, cur << 1 | 1, pos, val);
pushup(cur);
}
ll ans;
void query(int l, int r, int cur, int pos){
if(r <= pos){
ans = max(e[cur].maxx, ans + e[cur].sum);
return;
}
int mid = l + r >> 1;
query(l, mid, cur << 1, pos);
if(pos > mid) {
query(mid + 1, r, cur << 1 | 1, pos);
}
}
int main()
{
int q;
scanf("%d", &q);
build(1, 1e6, 1);
for(int i = 1; i <= q; i++){
char op[2];
int d, t;
scanf("%s", op);
if(op[0] == '+'){
scanf("%d %d", &t, &d);
update(1, 1000000, 1, t, d);
pos[i].t = t;
pos[i].d = d;
}
else if(op[0] == '-') {
scanf("%d", &d);
update(1, 1000000, 1, pos[d].t, -pos[d].d);
}
else {
scanf("%d", &t);
ans = 0;
query(1, 1000000, 1, t);
printf("%lld\n", max(0ll, ans - t));
}
}
return 0;
}