The Stream of Corning 2【可持久化线段树+离散化】【2018 ICPC Asia Nakhon Pathom Regional Contest K题】

Little Oregon loves to play in the forest, but tonight he got lost on his way back home. While trying to find his trail, he found a stream. No no, it was not a stream of hot water, rather it was a stream of 32 bit integers! Getting super excited, he sat by the stream and kept observing as the numbers kept coming. To his surprise, after coming out the numbers kept disappearing after a while! He asked Paka, the biggest tree by the stream, why the numbers were disappearing, and Paka replied that each number of the stream comes with an expiration time. Beyond its expiration point, that number gets eaten by the forest monster immediately. Each number has its own expiration time, and Paka offered that, as each number comes out, he will let Oregon know the expiration time of the number instantly. In exchange, sometimes Oregon will have to calculate the K’th smallest number of the numbers that has not expired yet, where K will be given by Paka. Oregon has recently signed up for ICPC Regional contest, so he thinks the deal Paka offered will be great for his practice. So let’s help Oregon with his regional al preparation. :) Input: Input starts with an integer T, then T cases follow. Each case starts with an integer, which represents the number of events E. Then E lines follow, each with one event. Each event is a list of integers separated by spaces.

A line of an event will be one of the following two types:

1. OP( = 1): CURRENT_TIMESTAMP VALUE END_TIMESTAMP This event starts with 1 which denotes the event type, followed by 3 integers: a. CURRENT_TIMESTAMP: the current timestamp b. VALUE: the value of the stream c. END_TIMESTAMP: the timestamp where this value will expire.

2. OP( = 2): CURRENT_TIMESTAMP K This event starts with 2 which denotes the event type, followed by 2 integers: a. CURRENT_TIMESTAMP: the current timestamp b. K: the position for the value that Paka is asking for. Explanation: Time is represented as a sequence of timestamps, which are 32 bit integers, the greater the timestamp implies the later the time. CURRENT_TIMESTAMP is the timestamp of a number coming out of the stream, or the timestamp of a query given by Paka. In the given inputs, the CURRENT_TIMESTAMPS will be strictly increasing between consecutive events.

And a number cannot expire before coming out of the stream, hence END_TIMESTAMP >= CURRENT_TIMESTAMP.

Constraints: 1. 1 = t. If no such number exists, then print -1.


  题意:给予这样的两种操作,(一)、开始时间、价值、结束时间;(二)、查询目前时间点的第K小的价值,如果没有K个的话,就输出-1。

  思路:我们用vector<>存每个离散时间戳上的加进去的值,还有要减去的值,然后因为题目中说的那样,查询时间是按照生序排列的,所以我们只需要去不断的进行对应的查询即可。查询第K大,用的是主席树的操作。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 2e5 + 7;
int E, lsan[maxN], cnt, lv[maxN], num, len_t, _UP, in, ou, root = 1;
struct qtion
{
    int L, R, val;
    qtion(int b=0, int c=0, int d=0):L(b), R(c), val(d) {}
}ques[maxN];
struct need
{
    int ti, k;
    need(int a=0, int b=0):ti(a), k(b) {}
}nd[maxN];
int tree[30 * maxN], lc[30 * maxN], rc[30 * maxN], tot;
inline void update(int &rt, int l, int r, int pos, int val)
{
    if(!rt)
    {
        rt = ++tot;
        tree[rt] = 0;
        lc[rt] = rc[rt] = 0;
    }
    tree[rt] += val;
    if(l == r) return;
    int mid = HalF;
    if(pos <= mid) update(lc[rt], l, mid, pos, val);
    else update(rc[rt], mid + 1, r, pos, val);
}
int query(int rt, int l, int r, int k)
{
    if(l == r) return l;
    int mid = HalF;
    if(tree[lc[rt]] >= k) return query(lc[rt], l, mid, k);
    else return query(rc[rt], mid + 1, r, k - tree[lc[rt]]);
}
vector<int> add[maxN], del[maxN];
inline void init()
{
    cnt = num = in = ou = 0;
    root = 1;
    tot = 1;
    tree[0] = lc[0] = rc[0] = 0;
    tree[1] = lc[1] = rc[1] = 0;
}
int main()
{
    int T;  scanf("%d", &T);
    for(int Cas=1; Cas<=T; Cas++)
    {
        scanf("%d", &E);
        init();
        for(int i=1, op; i<=E; i++)
        {
            scanf("%d", &op);
            if(op == 1)
            {
                ++in;
                scanf("%d%d%d", &ques[in].L, &ques[in].val, &ques[in].R);
                lsan[++cnt] = ques[in].L;
                lsan[++cnt] = ques[in].R;
                lv[++num] = ques[in].val;
            }
            else
            {
                ++ou;
                scanf("%d%d", &nd[ou].ti, &nd[ou].k);
                lsan[++cnt] = nd[ou].ti;
            }
        }
        sort(lsan + 1, lsan + cnt + 1);
        sort(lv + 1, lv + num + 1);
        len_t = (int)(unique(lsan + 1, lsan + cnt + 1) - lsan - 1);
        _UP = (int)(unique(lv + 1, lv + num + 1) - lv - 1);
        for(int i=1; i<=len_t; i++) { add[i].clear(); del[i].clear(); }
        for(int i=1; i<=in; i++)
        {
            ques[i].L = (int)(lower_bound(lsan + 1, lsan + len_t + 1, ques[i].L) - lsan);
            ques[i].R = (int)(lower_bound(lsan + 1, lsan + len_t + 1, ques[i].R) - lsan);
            ques[i].val = (int)(lower_bound(lv + 1, lv + _UP + 1, ques[i].val) - lv);
            add[ques[i].L].push_back(ques[i].val);
            del[ques[i].R].push_back(ques[i].val);
        }
        for(int i=1; i<=ou; i++) nd[i].ti = (int)(lower_bound(lsan + 1, lsan + len_t + 1, nd[i].ti) - lsan);
        int ti = 1;
        printf("Case %d:\n", Cas);
        for(int i=1; i<=ou; i++)
        {
            for(int j=ti, have; j<=nd[i].ti; j++)
            {
                have = (int)add[j].size();
                for(int k=0; k<have; k++)
                {
                    update(root, 1, _UP, add[j][k], 1);
                }
            }
            for(int j=ti, have; j<nd[i].ti; j++)
            {
                have = (int)del[j].size();
                for(int k=0; k<have; k++)
                {
                    update(root, 1, _UP, del[j][k], -1);
                }
            }
            if(tree[1] >= nd[i].k) printf("%d\n", lv[query(root, 1, _UP, nd[i].k)]);
            else printf("-1\n");
            int have = (int)del[nd[i].ti].size();
            for(int k=0; k<have; k++)
            {
                update(root, 1, _UP, del[nd[i].ti][k], -1);
            }
            ti = nd[i].ti + 1;
        }
    }
    return 0;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值