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));
        }
    }
}
相關文章
相關標籤/搜索