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

  • 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 longbool 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 DEBUGfreopen("..\\DEBUG\\IO\\1.in", "r", stdin);// freopen("my.out", "w", stdout);clock_t c1 = clock();
#endifint 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 DEBUGstd::cerr << "Time:" << clock() - c1 << "ms" << std::endl;
#endif return Accepted;
}
///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
///             __.'              ~.   .~              `.__
///           .'//                  \./                  \\`.
///        .'//                     |                     \\`.
///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
///     .'//.-"                 `-.  |  .-'                 "-.\\`.
///   .'//______.============-..   \ | /   ..-============.______\\`.
/// .'______________________________\|/______________________________`.

CF1089K King Kog‘s Reception(权值线段树)相关推荐

  1. 【bzoj2770】YY的Treap 权值线段树

    题目描述 志向远大的YY小朋友在学完快速排序之后决定学习平衡树,左思右想再加上SY的教唆,YY决定学习Treap.友爱教教父SY如砍瓜切菜般教会了YY小朋友Treap(一种平衡树,通过对每个节点随机分 ...

  2. 树套树 ----- P1975 [国家集训队]排队(树状数组套权值线段树求动态逆序对)

    解题思路: 首先我们知道交换两个数a[l]和a[r]a[l]和a[r]a[l]和a[r]影响到的区间是[l+1,r−1][l+1,r-1][l+1,r−1] 对于a[l]a[l]a[l],我们要减去[ ...

  3. 树套树 ---- 树状数组套权值线段树模板题 P2617 Dynamic Rankings 动态第K大

    题目链接 题目大意: 给你一个数组aaa,aaa有两个操作 询问aaa中[l,r][l,r][l,r]区间里面第kkk小的数是哪个? 修改axa_xax​为yyy 解题思路: 首先我们知道权值线段树是 ...

  4. codevs1688 求逆序对(权值线段树)

    1688 求逆序对  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果 题目描述 Description 给定一个序列a1,a2,-,an,如 ...

  5. 【HDU6701】Make Rounddog Happy【权值线段树+双向单调队列】

    题意:给你一个序列,求满足要求的子序列个数,其中要求为: 1.子序列的max-子序列长度len<=k 2.子序列中不出现重复的数字 题解:首先看到子序列max,很容易想到枚举最大值然后分治,这个 ...

  6. HDU-5249 KPI(STL or 权值线段树)

    题目链接 Problem Description 你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度.数十亿的请求被推到一个大管道后同时服务从管头拉取请求.让我们来定义每个请 ...

  7. Governing sand(权值线段树/主席树)

    链接:https://ac.nowcoder.com/acm/contest/887/C 来源:牛客网 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 65536K,其他语言13107 ...

  8. Minimum Inversion Number HDU - 1394(权值线段树/树状数组)

    The inversion number of a given number sequence a1, a2, -, an is the number of pairs (ai, aj) that s ...

  9. 权值线段树小结(hdu多校,普通平衡树,郁闷的出纳员)

    之前刷了一点主席树的题目,但是没有系统的做过权值线段树的题目.主席树是多根权值线段树的综合.权值线段树可以解决在总区间里求第k大的问题.在普通的线段树里,我们每一个节点维护的是权值大小.但是在权值线段 ...

  10. HDU1394(权值线段树)

    HDU1394(权值线段树) 题意: 给定一个0到n-1的数字组成的序列,可以将序列进行左移任意次,求所能组成序列的逆序对的最小值 题解: 利用权值线段树,我们先求出当前序列所能组成的逆序对, 然后依 ...

最新文章

  1. 人人都能学会的python编程教程14:高级特性1
  2. NYOJ-199 无线网络覆盖
  3. Flask 数据迁移 报错 Table 'xxx' is already defined for this MetaData instance
  4. 数据结构图之二(最小生成树--克鲁斯卡尔算法)
  5. 【接口测试】【postman】postman通过脚本获取Token并自动加入请求头实现Token的参数化
  6. Makefile函数使用
  7. vue数组修改不触发视图更新、vue向响应式对象添加或删除属性
  8. stm32 vscode 编译_vs code+gcc stm32编译环境搭建
  9. 如何获得CSDN深色模式(基于Edge的强制深色获取)
  10. 【短语学习】True(False) Positives (Negatives) 的含义和翻译
  11. Win10桌面背景(壁纸)导出工具
  12. prince2 成功的项目管理_清晖公开课受控环境下的项目管理PRINCE2认证培训(北京)...
  13. jQuery stop()用法
  14. 用python实现自动化翻译
  15. Cannot execute request on any known server或DiscoveryClient_UNKNOWN/DESKTOP-MQ8D0C9:8761
  16. [200902] 条件概率与独立事件
  17. 【语义分割】语义分割经典模块
  18. 微型计算机原理daa,单片微机原理、汇编与C51及接口技术(第2版)
  19. 汶川地震死亡人数5月26日消息
  20. qt弹窗界面模态设置

热门文章

  1. antd中如何实现分页勾选记住之前的选项
  2. Fibonacci数列练习题
  3. 安卓APP自动更新实现
  4. IOl:从文件夹中找到后缀名为TXT的文件,然后复制到指定的文件夹
  5. excel提取数字的方法
  6. 在 Web 浏览器上进行 RSS 阅读
  7. 电脑蓝屏代码大全及解决办法合集
  8. 樱道,空蝉,雨空,夏恋,雨道,彩月,幻昼,惊梦,白夜。这些纯音乐
  9. buildroot制作树莓派CM3的系统
  10. 关于core_cm3.c和core_cm3.h,Core_cmFunc.h 和 Core_cmInstr.h的理解