CF1089K King Kog‘s Reception(权值线段树)

题目是个队列问题,涉及到进队,出队,查询三种操作

  • t d ,表示在时刻 t 某个骑士来访,需要和国王交谈 d 的时间。(进队)
    − i ,表示撤销第 i 次操作,第i次请求来访的骑士突然变卦,取消了访问请求。(出队)
    ? t ,表示询问公主在时刻 t 请求访问国王,她需要等多久才能轮到她。

注意到时间值域是 [1,1e6] ,考虑使用权值线段树维护这个队列。线段树上的一个点代表一个时间段,前两个操作对应线段树的单点修改,第三个操作对应线段树的区间查询。具体维护的信息见代码注释。

#include<bits/stdc++.h>
#define Accepted 0
using Azir = int;
namespace fastIO {
#define BUF_SIZE 100000
#define DECIMAL 6   
#define LL long long
    bool IOerror = 0;
    inline char nc() { static char buf[BUF_SIZE], * p1 = buf + BUF_SIZE, * pend = buf + BUF_SIZE; if (p1 == pend) { p1 = buf; pend = buf + fread(buf, 1, BUF_SIZE, stdin); if (pend == p1) { IOerror = 1; return -1; } }return *p1++; }
    inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
    template<class T> inline bool read(T& x) { bool sign = 0; char ch = nc(); x = 0; for (; blank(ch); ch = nc()); if (IOerror)return false; if (ch == '-')sign = 1, ch = nc(); for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0'; if (sign)x = -x; return true; }
    inline bool read(unsigned long long& x) { char ch = nc(); x = 0; for (; blank(ch); ch = nc()); if (IOerror)return false; for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0'; return true; }
    inline bool read(unsigned int& x) { char ch = nc(); x = 0; for (; blank(ch); ch = nc()); if (IOerror)return false; for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0'; return true; }
    inline bool read(double& x) { bool sign = 0; char ch = nc(); x = 0; for (; blank(ch); ch = nc()); if (IOerror)return false; if (ch == '-')sign = 1, ch = nc(); for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0'; if (ch == '.') { double tmp = 1; ch = nc(); for (; ch >= '0' && ch <= '9'; ch = nc())tmp /= 10.0, x += tmp * (ch - '0'); }if (sign)x = -x; return true; }
    inline bool read(char* s) { char ch = nc(); for (; blank(ch); ch = nc()); if (IOerror)return false; for (; !blank(ch) && !IOerror; ch = nc())*s++ = ch; *s = 0; return true; }
    inline bool read(char& c) { for (c = nc(); blank(c); c = nc()); if (IOerror) { c = -1; return false; }return true; }
    inline bool read(std::string& s) { s.clear(); char ch = nc(); for (; blank(ch); ch = nc()); if (IOerror)return false; for (; !blank(ch) && !IOerror; ch = nc())s += ch; return true; }
    template<class T, class... U>bool read(T& h, U&... t) { return read(h) && read(t...); }
    struct Ostream_fwrite {
        char* buf, * p1, * pend;
        Ostream_fwrite() { buf = new char[BUF_SIZE]; p1 = buf; pend = buf + BUF_SIZE; }
        inline void out(char ch) { if (p1 == pend) { fwrite(buf, 1, BUF_SIZE, stdout); p1 = buf; }*p1++ = ch; }
        template<class T>inline void print(T x) { static char s[41], * s1; s1 = s; if (!x)*s1++ = '0'; if (x < 0)out('-'), x = -x; while (x)*s1++ = x % 10 + '0', x /= 10; while (s1-- != s)out(*s1); }
        inline void print(char ch) { out(ch); }
        inline void print(unsigned long long x) { static char s[41], * s1; s1 = s; if (!x)*s1++ = '0'; while (x)*s1++ = x % 10 + '0', x /= 10; while (s1-- != s)out(*s1); }
        inline void print(unsigned int x) { static char s[41], * s1; s1 = s; if (!x)*s1++ = '0'; while (x)*s1++ = x % 10 + '0', x /= 10; while (s1-- != s)out(*s1); }
        inline void print(double x, int y = DECIMAL) {
            static LL mul[] = { 1,10,100,1000,10000,100000,1000000,10000000,100000000,
                             1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
                             100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL };
            if (x < -1e-12)out('-'), x = -x; x *= mul[y];
            LL x1 = (LL)floor(x); if (x - floor(x) >= 0.5)++x1;
            LL x2 = x1 / mul[y], x3 = x1 - x2 * mul[y]; print(x2);
            if (y > 0) { out('.'); for (size_t i = 1; i < y && x3 * mul[i] < mul[y]; out('0'), ++i); print(x3); }

        }
        inline void print(char* s) { while (*s)out(*s++); }
        inline void print(const char* s) { while (*s)out(*s++); }
        inline void print(std::string s) { print(s.c_str()); }
        inline void flush() { if (p1 != buf) { fwrite(buf, 1, p1 - buf, stdout); p1 = buf; } }
        ~Ostream_fwrite() { flush(); }
    }Ostream;
    template<class T>inline void print(T x) { Ostream.print(x); }
    template<class T>inline void println(T x) { Ostream.print(x); Ostream.out('\n'); }
    inline void print(double x, int y = DECIMAL) { Ostream.print(x, y); }
    inline void println(double x, int y = DECIMAL) { Ostream.print(x, y); Ostream.out('\n');; }
    template<class T, class... U>void print(const T& h, const U&... t) { print(h); Ostream.out(' ');; print(t...); }
    template<class T, class... U>void println(const T& h, const U&... t) { print(h); Ostream.out(' ');; println(t...); }
    inline void flush() { Ostream.flush(); }
    // C   int,long long ,__int128,unsigned long long,unsigned int,double,char[],char
    // c++ string
#undef LL
#undef DECIMAL
#undef BUF_SIZE
};
using namespace fastIO;
typedef long long LL;
using namespace std;

const int32_t MAXN = 1e6 + 5;

struct node
{
    LL sum;//在该区间内时间点来访问的骑士 的谈话时间总和
    LL ending;//结束 所有在该区间内时间点 来访的骑士 谈话 的 时间
    bool empty;//是否有效
    node(bool f = false) {
        sum = 0;
        empty = f;
    }

}d[MAXN << 2];
node operator +(const node& a, const node& b)//重载 + 运算符  ,对应了 左右两个区间的合并方式
{
    //a 左区间  b 右区间
    //c 由 左右子区间 合并而成的区间
    node c;
    if (a.empty)return b;//某一个为空 直接返回另外一个 //不作合并
    if (b.empty)return a;
    c.ending = max(a.ending + b.sum, b.ending);//这里是核心  左区间的最终完成时间+右区间的总交谈时间  和 右区间的最终完成时间 取max
    //对于取max,举个例子会比较容易理解
    //比如说  线段树上该点代表的 是 [4,8] 这个时间段  ,会出现两种 情况 
    // 1 :假设有一个骑士 在 时刻5 来访,需要交谈 2个时刻  ,那么他和国王的谈话在时刻 7 结束
    //     然而这个区间的ending并不是7,它本身就是[4,8] ,当然是在时刻8 结束了 ,也就是 max(7,8) 保证了正确的ending  不妨认为这是个较为空闲的时间段,ending即本身时间段的ending
    // 2 : 假设有一个骑士 在 时刻5 来访,需要交谈 10个时刻,那么他和国王的谈话在时刻 15 结束
    //     此时这个区间的ending就是15,它超出了 原本的[4,8],还多占用了 7个时刻 ,也就是 max(15,8)  不妨认为这是个繁忙的时间段,繁忙到不得不占用后面时间段的时间。
    c.sum = a.sum + b.sum;
    return c;
}
LL a[MAXN];
#define lson rt<<1
#define rson rt<<1|1
inline void push_up(int rt)
{
    d[rt] = d[lson] + d[rson];
}
void build(int l, int r, int rt)
{
    if (l == r)
    {
        d[rt].sum = 0;
        d[rt].ending = l;
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, lson);
    build(mid + 1, r, rson);
    push_up(rt);
}

void modify(int x, LL c, int l, int r, int rt)
{
    if (l == r) {
        d[rt].sum += c;
        d[rt].ending += c;
        return;
    }
    int mid = (l + r) >> 1;

    if (x <= mid)modify(x, c, l, mid, lson);
    if (x >= mid + 1)modify(x, c, mid + 1, r, rson);
    push_up(rt);
}



node query(int L, int R, int l, int r, int rt)
{
    node res(true);// res置为空,只起到连接作用,不参与 +号运算 
    if (L <= l && r <= R)
    {
        return d[rt];
    }
    int mid = (l + r) >> 1;
    if (L <= mid) res = res + query(L, R, l, mid, lson);
    if (R >= mid + 1)res = res + query(L, R, mid + 1, r, rson);
    return res;
}

int p[MAXN];
LL v[MAXN];

Azir main()
{
#ifdef DEBUG
    freopen("..\\DEBUG\\IO\\1.in", "r", stdin);
    // freopen("my.out", "w", stdout);
    clock_t c1 = clock();
#endif
    int n;
    read(n);
    int MAXT = 1e6;
    build(1, MAXT, 1);
    for (int i = 1; i <= n; i++)
    {
        char op;
        int x; LL y;
        read(op);
        if (op == '+') {
            read(x, y);
            modify(x, y, 1, MAXT, 1);
            p[i] = x;
            v[i] = y;
        }
        else if (op == '-')
        {
            read(x);
            modify(p[x], -v[x], 1, MAXT, 1);
        }
        else
        {
            read(x);
            println(query(1, x, 1, MAXT, 1).ending - x);
            //注意求的是公主的等待时间,而线段树上维护的是全局等待时间,所以要减去公主来的时间点 x
        }
    }



    fastIO::flush();
#ifdef DEBUG
    std::cerr << "Time:" << clock() - c1 << "ms" << std::endl;
#endif 
    return Accepted;
}
///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
///             __.'              ~.   .~              `.__
///           .'//                  \./                  \\`.
///        .'//                     |                     \\`.
///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
///     .'//.-"                 `-.  |  .-'                 "-.\\`.
///   .'//______.============-..   \ | /   ..-============.______\\`.
/// .'______________________________\|/______________________________`.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值