Codeforces 1089K - King Kog's Reception - [线段树][2018-2019 ICPC, NEERC, Northern Eurasia Finals Probl

题目连接:https://codeforces.com/contest/1089/problem/Knode

time limit per test: 2 seconds  memory limit per test: 512 megabytesc++

King Kog got annoyed of the usual laxity of his knights — they can break into his hall without prior notice! Thus, the King decided to build a reception with a queue where each knight chooses in advance the time when he will come and how long the visit will take. The knights are served in the order of the recorded time, but each knight has to wait until the visits of all the knights before him are finished.ide

Princess Keabeanie wants to see her father. However, she does not want to interrupt the knights so she joins the queue. Unfortunately, the knights change their minds very often — they can join the queue or cancel their visits. Please help the princess to understand how long she will have to wait until she sees her father if she enters the queue at the specified moments of time given the records at the reception.ui

Input
The first line of the input contains a single integer $q (1 \le q \le 3 \times 10^5)$ — the number of events. An event can be of three types: join, cancel, or query.spa

Join "+ $t$ $d$" $(1 \le t,d \le 10^6)$ — a new knight joins the queue, where $t$ is the time when the knight will come and $d$ is the duration of the visit.
Cancel "- $i$" $(1 \le i \le q)$ — the knight cancels the visit, where $i$ is the number (counted starting from one) of the corresponding join event in the list of all events.
Query "? $t$" $(1 \le t \le 10^6)$ — Keabeanie asks how long she will wait if she comes at the time $t$.
It is guaranteed that after each event there are no two knights with the same entrance time in the queue. Cancel events refer to the previous joins that were not cancelled yet.code

Keabeanie can come at the same time as some knight, but Keabeanie is very polite and she will wait for the knight to pass.blog

Output
For each query write a separate line with the amount of time Keabeanie will have to wait.three

Example
input
19
? 3
+ 2 2
? 3
? 4
+ 5 2
? 5
? 6
+ 1 2
? 2
? 3
? 4
? 5
? 6
? 7
? 9
- 8
? 2
? 3
? 6
output
0
1
0
2
1
3
2
1
2
1
0
0
2
1
1队列

 

题意:ci

国王构建了一个队列,骑士若是要来见国王,都要经过这个队列排队觐见国王。

给出三种操做,第一种表明骑士在 $t$ 时刻前来排队,它要跟国王商谈 $d$ 分钟(保证没有两个骑士同时到来)。

第二种表明第 $i$ 次操做,其所表明的那个来排队的骑士取消了此次觐见。

第三种表明公主在 $t$ 时刻也前来排队,询问她须要等多久才能就到父王(若是她和某个骑士同时到达,则她会礼让骑士)。

 

题解:

假设在某个时间区间 $[l,r]$ 内全部前来觐见的骑士,他们的 $d$ 之和为 $sum[l,r]$。

那么对于一次查询操做 $t$,必然有某个时刻 $i$ 来的这个骑士,其对应的 $i + sum[i][t]$ 正好就是公主要等到的那个时刻。

也就是说,只要求 $\max_{1 \le i \le t}(sum[i][t]+i) - t$ 便可。

所以,咱们能够用线段树来进行维护,线段树节点有两个值 $sum$ 和 $mx$:$sum[l,r]$ 的意义如上所述;而 $mx[l,r]$ 则表明至少要到 $mx[l,r]$ 时刻才能见完 $[l,r]$ 区间内的全部骑士。

这两个值的维护方式以下,特别是 $mx$ 的维护是值得注意的:

node[rt].sum=node[ls].sum+node[rs].sum;
node[rt].mx=max(node[rs].mx,node[ls].mx+node[rs].sum);

 

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxq=3e5+10;
const int maxt=1e6+10;
int q;
pii et[maxq];

/********************************* Segment Tree - st *********************************/
#define ls (rt<<1)
#define rs (rt<<1|1)
struct Node{
    int l,r;
    ll sum,mx;
}node[4*maxt];
void pushup(int rt)
{
    node[rt].sum=node[ls].sum+node[rs].sum;
    node[rt].mx=max(node[rs].mx,node[ls].mx+node[rs].sum);
}
void build(int rt,int l,int r)
{
    node[rt].l=l; node[rt].r=r;
    if(l==r)
    {
        node[rt].sum=0, node[rt].mx=l;
        return;
    }
    int mid=(l+r)/2;
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup(rt);
}
void update(int rt,int pos,int val)
{
    if(node[rt].l==node[rt].r)
    {
        node[rt].sum+=val;
        node[rt].mx+=val;
        return;
    }
    int mid=(node[rt].l+node[rt].r)/2;
    if(pos<=mid) update(ls,pos,val);
    if(pos>mid) update(rs,pos,val);
    pushup(rt);
}
ll ans;
void query(int rt,int t)
{
    if(node[rt].r<=t)
    {
        ans=max(node[rt].mx,ans+node[rt].sum);
        return;
    }
    int mid=(node[rt].l+node[rt].r)/2;
    query(ls,t);
    if(mid<t) query(rs,t);
}
/********************************* Segment Tree - ed *********************************/

int main()
{
    cin>>q;
    build(1,1,1000000);
    for(int i=1;i<=q;i++)
    {
        char op[2]; scanf("%s",op);
        if(op[0]=='+')
        {
            int t,d; scanf("%d%d",&t,&d);
            update(1,t,d);
            et[i]=make_pair(t,d);
        }
        if(op[0]=='-')
        {
            int id; scanf("%d",&id);
            update(1,et[id].first,-et[id].second);
        }
        if(op[0]=='?')
        {
            int t; scanf("%d",&t);
            ans=0; query(1,t);
            printf("%I64d\n",max(ans-t,0ll));
        }
    }
}
相关文章
相关标签/搜索