题目大意:有$n$个位置,$m$个操作。操作有两种:

  1. $1\;l\;r\;x:$在区间$[l,r]$每个位置加上一个数$x$
  2. $2\;l\;r\;k:$询问$[l,r]$中第$k$大的数是多少。

题解:树套树,权值线段树套位置线段树,要标记永久化,不然会$TLE$

卡点:没有标记永久化,$TLE$,然后处理$tag$部分写错

C++ Code:

#include <cstdio>
#include <algorithm>
#include <cctype>
namespace __IO {
namespace R {
int x, ch, f;
inline int readsign() {
f = 1;
while (isspace(ch = getchar()));
if (ch == '-') f = -1;
for (x = ch & 15; isdigit(ch = getchar()); ) x = x * 10 + (ch & 15);
return x * f;
}
inline int read() {
while (isspace(ch = getchar()));
for (x = ch & 15; isdigit(ch = getchar()); ) x = x * 10 + (ch & 15);
return x;
} long long X;
inline long long readll() {
while (isspace(ch = getchar()));
for (X = ch & 15; isdigit(ch = getchar()); ) X = X * 10 + (ch & 15);
return X;
}
}
}
using __IO::R::read;
using __IO::R::readsign;
using __IO::R::readll; #define maxn 50010 int n, m; namespace SgT2 {
#define N ((maxn << 3) * 50)
int lc[N], rc[N], tg[N], idx;
int L, R;
long long V[N]; void __insert(int &rt, const int l, const int r) {
if (!rt) rt = ++idx;
V[rt] += std::min(R, r) - std::max(L, l) + 1;
if (L <= l && R >= r) {
tg[rt]++;
return ;
}
int mid = l + r >> 1;
if (L <= mid) __insert(lc[rt], l, mid);
if (R > mid) __insert(rc[rt], mid + 1, r);
}
void insert(int &rt, int __L, int __R) {
L = __L, R = __R;
__insert(rt, 1, n);
} long long __query(const int rt, const int l, const int r) {
if (!rt || (L <= l && R >= r)) return V[rt];
int mid = l + r >> 1;
long long res = static_cast<long long> (std::min(R, r) - std::max(L, l) + 1) * tg[rt];
if (L <= mid) res += __query(lc[rt], l, mid);
if (R > mid) res += __query(rc[rt], mid + 1, r);
return res;
}
long long query(int rt, int __L, int __R) {
L = __L, R = __R;
return __query(rt, 1, n);
}
#undef N
} namespace SgT {
#define N (maxn << 3)
const int maxl = -50000, maxr = 50000;
int root[N];
int L, R, num;
void __insert(const int rt, const int l, const int r) {
SgT2::insert(root[rt], L, R);
if (l == r) return ;
int mid = l + r >> 1;
if (num <= mid) __insert(rt << 1, l, mid);
else __insert(rt << 1 | 1, mid + 1, r);
}
void insert(int __L, int __R, int __num) {
L = __L, R = __R, num = __num;
__insert(1, maxl, maxr);
} long long pos;
int __query(const int rt, const int l, const int r) {
if (l == r) return l;
int mid = l + r >> 1;
long long tmp = SgT2::query(root[rt << 1 | 1], L, R);
if (pos <= tmp) return __query(rt << 1 | 1, mid + 1, r);
else {
pos -= tmp;
return __query(rt << 1, l, mid);
}
}
int query(int __L, int __R, long long __pos) {
L = __L, R = __R, pos = __pos;
return __query(1, maxl, maxr);
}
#undef N
}
using SgT::insert;
using SgT::query; int main() {
n = read(), m = read();
while (m --> 0) {
int op = read(), l = read(), r = read();
if (op == 1) {
int c = readsign();
insert(l, r, c);
} else {
long long c = readll();
printf("%d\n", query(l, r, c));
}
}
return 0;
}

  

[洛谷P3332][ZJOI2013]K大数查询的更多相关文章

  1. 洛谷 P3332 [ZJOI2013]K大数查询 解题报告

    P3332 [ZJOI2013]K大数查询 题目描述 有\(N\)个位置,\(M\)个操作.操作有两种,每次操作如果是\(\tt{1\ a\ b\ c}\)的形式表示在第\(a\)个位置到第\(b\) ...

  2. 洛谷 P3332 [ZJOI2013]K大数查询 (整体二分理解)

    链接: P3332 题意: 维护 \(n(1\leq n\leq 5\times10^4)\) 个可重整数集,编号从 \(1\) 到 \(n\).有 \(m(1\leq m\leq5\times10^ ...

  3. 洛谷P3332 [ZJOI2013]K大数查询 权值线段树套区间线段树_标记永久化

    Code: #include <cstdio> #include <algorithm> #include <string> #include <cstrin ...

  4. 洛谷 P3332 [ZJOI2013]K大数查询 || bzoj3110

    用树套树就很麻烦,用整体二分就成了裸题.... 错误: 1.尝试线段树套平衡树,码农,而且n*log^3(n)慢慢卡反正我觉得卡不过去 2.线段树pushdown写错...加法tag对于区间和的更新应 ...

  5. P3332 [ZJOI2013]K大数查询(线段树套线段树+标记永久化)

    P3332 [ZJOI2013]K大数查询 权值线段树套区间线段树 把插入的值离散化一下开个线段树 蓝后每个节点开个线段树,维护一下每个数出现的区间和次数 为了防止MLE动态开点就好辣 重点是标记永久 ...

  6. P3332 [ZJOI2013]K大数查询

    传送门 注意操作 $1$ 是在区间的每个位置加入一个数,不是加上一个值 相当于每个位置维护的是一个集合 显然树套树 一开始想的是区间线段树套权值线段树 发现这样询问区间第 $K$ 大时就要先二分答案再 ...

  7. P3332 [ZJOI2013]K大数查询 整体二分

    终于入门整体二分了,勉勉强强算是搞懂了一个题目吧. 整体二分很多时候可以比较好的离线处理区间\(K\)大值的相关问题.考虑算法流程: 操作队列\(arr\),其中有询问和修改两类操作. 每次在答案的可 ...

  8. 【BZOJ3110】【LG3332】[ZJOI2013]K大数查询

    [BZOJ3110][LG3332][ZJOI2013]K大数查询 题面 洛谷 BZOJ 题解 和普通的整体分治差不多 用线段树维护一下每个查询区间内大于每次二分的值\(mid\)的值即可 然后再按套 ...

  9. BZOJ 3110: [Zjoi2013]K大数查询 [树套树]

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[Submit][Sta ...

随机推荐

  1. clr via c#读书笔记五:常量和字段

    1.常量是值从不变化的符号.只能定义编译器识别的基元类型的常量.如:Boolean,Char,Byte,SByte,Int16,UInt16,Int32,UInt32,Int64,Single,Dou ...

  2. DMA是什么意思

    DMA是让硬盘不用通过CPU来控制读写 它的意思是直接存储器存取,是一种快速传送数据的机制,DMA技术的重要性在于,利用它进行数据存取时不需要CPU进行干预,可提高系统执行应用程序的效率.利用DMA传 ...

  3. 角色 RESOURCE、CONNECT、DBA具有的权限

    角色 RESOURCE.CONNECT.DBA具有的权限 select grantee,privilege from dba_sys_privs where grantee='RESOURCE' or ...

  4. Ubuntu目录与权限

    Ubuntu目录 / /bin /sbin /boot /etc /mnt /home d :directory - :file b :block  磁盘以块进行 l :link Ubuntu权限 U ...

  5. Qt 独立运行时伴随CMD命令窗口

    用Qt写了一个小软件,在把程序release后,打包分装后,发现程序运行的时候会伴随cmd命令窗口,可把我愁怀了 不过功夫不负有心人,在老师和我网友的帮助下,终于搞完了 CONFIG:指定工程配置和编 ...

  6. Linux命令应用大词典-第 15章 文件、目录权限和属性

    15.1 chmod:更改文件和目录的模式 15.2 chown:更改文件和目录的用户所有者和组群所有者 15.3 chgrp:更改文件或目录的所属组 15.4 umask:显示和设置文件及目录创建默 ...

  7. Unity编辑器 - Rigidbody动力学Bake到AnimationClip

    Unity编辑器 - Rigidbody动力学Bake到AnimationClip Unity文档移动平台优化部分提到Physics对CPU的消耗较大 将动力学的特效如破碎等Bake成动画也是优化性能 ...

  8. GIT: 分布式开发 代码管理工具使用命令大全

    代码管理工具: GIT     什么是GIT? Git是一款免费.开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目 Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常 ...

  9. 小程序开发中,纯css实现内容收起折叠功能

    不多说,直接上代码: wxml页面: <!--收起折叠 begin--> <view style='width:100%;background:#fff;border-top:1px ...

  10. Ubuntu—终端命令调整窗口的大小

    1,查看窗口大小 current 1280x768 是我当前电脑的窗口大小,下面提供的是可以修改的窗口大小. $ xrandr 2.修改窗口大小 示例: $ xrandr -s 1024x768