[BZOJ3110][ZJOI2013]K大数查询(线段树套线段树)
来源:互联网 发布:彩虹秒赞最新源码 编辑:程序博客网 时间:2024/05/16 12:36
有很多种解法。这里讲一种线段树套线段树的解法。这里外层的线段树是权值线段树,而内层的是位置线段树(保存对应权值范围的出现次数)。在空间问题上,使用动态开点。
对于修改,可以看作是对于权值
对于询问,可以在权值线段树上二分,即如果右子节点(右子权值区间)所嵌套的线段树的
整体二分解法:http://blog.csdn.net/qq_18455665/article/details/50707462
代码:
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define p2 p << 1#define p3 p << 1 | 1using namespace std;inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res;}typedef unsigned int ui;typedef long long ll;const int N = 4e5 + 5, M = 18e6 + 5;int n, m, rt[N], QAQ;struct cyx { int lc, rc; ui sum, add; void init() { lc = rc = sum = add = 0; }} T[M];inline void modify(const int &l, const int &r, const int &s,const int &e, int &p) { if (!p) T[p = ++QAQ].init(); if (l == s && r == e) return (void) (T[p].add++); int mid = l + r >> 1; if (T[p].add) { if (!T[p].lc) T[T[p].lc = ++QAQ].init(); if (!T[p].rc) T[T[p].rc = ++QAQ].init(); T[T[p].lc].add += T[p].add; T[T[p].rc].add += T[p].add; T[p].add = 0; } if (e <= mid) modify(l, mid, s, e, T[p].lc); else if (s >= mid + 1) modify(mid + 1, r, s, e, T[p].rc); else modify(l, mid, s, mid, T[p].lc), modify(mid + 1, r, mid + 1, e, T[p].rc); T[p].sum = T[T[p].lc].sum + T[T[p].rc].sum + T[T[p].lc].add * (mid - l + 1) + T[T[p].rc].add * (r - mid);}inline void change(const int &l, const int &r, const int &s,const int &e, const int &v, const int &p) { modify(1, n, s, e, rt[p]); if (l == r) return; int mid = l + r >> 1; if (v <= mid) change(l, mid, s, e, v, p2); else change(mid + 1, r, s, e, v, p3);}inline ui query(const int &l, const int &r, const int &s,const int &e, int &p) { if (!p) T[p = ++QAQ].init(); if (l == s && r == e) return T[p].sum + T[p].add * (r - l + 1); int mid = l + r >> 1; if (T[p].add) { if (!T[p].lc) T[T[p].lc = ++QAQ].init(); if (!T[p].rc) T[T[p].rc = ++QAQ].init(); T[T[p].lc].add += T[p].add; T[T[p].rc].add += T[p].add; T[p].add = 0; } ui res; if (e <= mid) res = query(l, mid, s, e, T[p].lc); else if (s >= mid + 1) res = query(mid + 1, r, s, e, T[p].rc); else res = query(l, mid, s, mid, T[p].lc) + query(mid + 1, r, mid + 1, e, T[p].rc); T[p].sum = T[T[p].lc].sum + T[T[p].rc].sum + T[T[p].lc].add * (mid - l + 1) + T[T[p].rc].add * (r - mid); return res;}inline int ask(const int &l, const int &r, const int &s,const int &e, const ll &c, const int &p) { if (l == r) return l; int mid = l + r >> 1; ui tmp = query(1, n, s, e, rt[p3]); if (c <= tmp) return ask(mid + 1, r, s, e, c, p3); else return ask(l, mid, s, e, c - tmp, p2);}int main() { int a, b, c, op; n = read(); m = read(); ll d; while (m--) { op = read(); a = read(); b = read(); op == 1 ? c = read() : scanf("%lld", &d); if (op == 1) change(1, n, a, b, c, 1); else printf("%d\n", ask(1, n, a, b, d, 1)); } return 0;}
阅读全文
0 0
- bzoj3110[Zjoi2013]K大数查询 主席树套线段树
- [BZOJ3110][ZJOI2013]K大数查询(线段树套线段树)
- [BZOJ3110][Zjoi2013]K大数查询(主席树套线段树||整体二分 )
- 【BZOJ3110】K大数查询(ZJOI2013)-整体二分+线段树
- 【BZOJ3110】【Zjoi2013】K大数查询 树套树 权值线段树套区间线段树
- 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树
- 【bzoj3110】【ZJOI2013】【K大数查询】【权值线段树套位置线段树】
- [BZOJ3110]K大数查询|线段树套线段树
- 【ZJOI2013】K 大数查询 ( 树状数组套线段树 )
- BSOJ3723:ZJOI2013 k大数查询 线段树套线段树
- 【线段树套线段树】[ZJOI 2013] bzoj3110 K大数查询
- 【BZOJ3110】【codevs1616】K大数查询,权值线段树套普通线段树
- bzoj3110: [Zjoi2013]K大数查询 树套数
- BZOJ 3110: [Zjoi2013]K大数查询|线段树套线段树
- 3110: [Zjoi2013]K大数查询 线段树套线段树 标记永久化
- bzoj 3110: [Zjoi2013]K大数查询 线段树套线段树
- bzoj3110 K大数查询(整体二分+线段树)
- bzoj3110 k大数查询 zjoi2013
- C#操作XML方法集合
- Lintcode 5. 第k大元素
- node项目部署linux
- Python之路【第2天】
- struts解决异常抛出的两种方法
- [BZOJ3110][ZJOI2013]K大数查询(线段树套线段树)
- 机房重构总结3
- Python系列学习笔记(一)——入门学习
- 朴素贝叶斯法
- 写在人生特别的一天,烙在内心深处的感触
- 算法导论的C++实现(签到)
- Database—数据库基础
- Verilog序列检测器-两例
- Java 23种设计模式之原型模式