P3332 [ZJOI2013]K大数查询
注意操作 $1$ 是在区间的每个位置加入一个数,不是加上一个值
相当于每个位置维护的是一个集合
显然树套树
一开始想的是区间线段树套权值线段树
发现这样询问区间第 $K$ 大时就要先二分答案再用 $O(log^2_n)$ 时间查询
那么单次询问的复杂度就有 $O(log^3_n)$ ,显然不行
考虑权值线段树套区间线段树
单次插入复杂度还是 $O(log^2_n)$,询问时只要在权值线段树上二分就行
那么单次操作复杂度就是 $O(log^2_n)$
据说此题很卡常,为了防止我的大常数导致 $GG$ 所以学了一下线段树的标记用久化
简单说就是标记不下传,只要询问时把经过节点的标记加进来一起计算贡献,代码不难想
因为空间问题所以内层的区间线段树要动态开点
因为插入的数可能为负,所以要离散化,注意 $long long$ !
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
inline ll readll()
{
ll x=; int f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e5+,M=2e7+;
int n,m,cnt,A[N],T;
int rt[N],L[M],R[M],tag[M];//区间线段树的数组,根节点,左儿子,右儿子,永久标记
ll sum[M];//区间线段树数组,区间和
int ql,qr; ll res;
void add(int &o,int l,int r)//区间加1
{
if(!o) o=++cnt;//动态开点
sum[o]+= max( min(r,qr)-max(l,ql)+ ,) ;//因为永久标记所以要这样更新sum
if(l>=ql&&r<=qr) { tag[o]++; return; }//注意我的tag是给儿子的,要先更新sum
int mid=l+r>>;
if(ql<=mid) add(L[o],l,mid);
if(qr>mid) add(R[o],mid+,r);
}
void query(int o,int l,int r,int tot)//区间求和,tot维护当前经过节点的tag的和
{
if(l>=ql&&r<=qr) { res+=sum[o]+1ll*(r-l+)*tot; return; }//更新res
int mid=l+r>>;
if(ql<=mid) query(L[o],l,mid,tot+tag[o]);
if(qr>mid) query(R[o],mid+,r,tot+tag[o]);
}
int POS,RES; ll K;
void ADD(int o,int l,int r)//权值线段树插入
{
add(rt[o],,n); if(l==r) return;
int mid=l+r>>;
if(POS<=mid) ADD(o<<,l,mid);
else ADD(o<<|,mid+,r);
}
void QUERY(int o,int l,int r)//权值线段树处理询问
{
if(l==r) { RES=A[l]; return; }
int mid=l+r>>;
res=; query(rt[o<<|],,n,);//注意优先走大的!
if(res<K) { K-=res; QUERY(o<<,l,mid); }
else QUERY(o<<|,mid+,r);
}
int op[N],dl[N],dr[N],dk[N];//读入的数据
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
n=read(),m=read();
for(int i=;i<=m;i++)
{
op[i]=read(),dl[i]=read(),dr[i]=read(),dk[i]=readll();
if(op[i]==) A[++T]=dk[i];
}
sort(A+,A+T+);
T=unique(A+,A+T+)-A-;//离散化
for(int i=;i<=m;i++)
if(op[i]==) dk[i]=lower_bound(A+,A+T+,dk[i])-A;
for(int i=;i<=m;i++)
{
ql=dl[i],qr=dr[i];
if(op[i]==) { POS=dk[i]; ADD(,,T); }
else
{
K=dk[i]; QUERY(,,T);
printf("%d\n",RES);
}
}
return ;
}
P3332 [ZJOI2013]K大数查询的更多相关文章
- P3332 [ZJOI2013]K大数查询(线段树套线段树+标记永久化)
P3332 [ZJOI2013]K大数查询 权值线段树套区间线段树 把插入的值离散化一下开个线段树 蓝后每个节点开个线段树,维护一下每个数出现的区间和次数 为了防止MLE动态开点就好辣 重点是标记永久 ...
- 洛谷 P3332 [ZJOI2013]K大数查询 解题报告
P3332 [ZJOI2013]K大数查询 题目描述 有\(N\)个位置,\(M\)个操作.操作有两种,每次操作如果是\(\tt{1\ a\ b\ c}\)的形式表示在第\(a\)个位置到第\(b\) ...
- 洛谷 P3332 [ZJOI2013]K大数查询 (整体二分理解)
链接: P3332 题意: 维护 \(n(1\leq n\leq 5\times10^4)\) 个可重整数集,编号从 \(1\) 到 \(n\).有 \(m(1\leq m\leq5\times10^ ...
- P3332 [ZJOI2013]K大数查询 整体二分
终于入门整体二分了,勉勉强强算是搞懂了一个题目吧. 整体二分很多时候可以比较好的离线处理区间\(K\)大值的相关问题.考虑算法流程: 操作队列\(arr\),其中有询问和修改两类操作. 每次在答案的可 ...
- [洛谷P3332][ZJOI2013]K大数查询
题目大意:有$n$个位置,$m$个操作.操作有两种: $1\;l\;r\;x:$在区间$[l,r]$每个位置加上一个数$x$ $2\;l\;r\;k:$询问$[l,r]$中第$k$大的数是多少. 题解 ...
- 洛谷P3332 [ZJOI2013]K大数查询 权值线段树套区间线段树_标记永久化
Code: #include <cstdio> #include <algorithm> #include <string> #include <cstrin ...
- 洛谷 P3332 [ZJOI2013]K大数查询 || bzoj3110
用树套树就很麻烦,用整体二分就成了裸题.... 错误: 1.尝试线段树套平衡树,码农,而且n*log^3(n)慢慢卡反正我觉得卡不过去 2.线段树pushdown写错...加法tag对于区间和的更新应 ...
- BZOJ 3110: [Zjoi2013]K大数查询 [树套树]
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6050 Solved: 2007[Submit][Sta ...
- 树套树专题——bzoj 3110: [Zjoi2013] K大数查询 & 3236 [Ahoi2013] 作业 题解
[原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 978 Solved: 476 Descri ...
随机推荐
- C++——STL之vector, list, deque容器对比与常用函数
STL 三种顺序容器的特性对比: vector 可变数组,内存空间是连续的,容量不会进行缩减.支持高效随机存取,即支持[]和at()操作.尾部插入删除效率高,其他位置插删效率较低: list 双向链表 ...
- 面试题:Java必知必会:异常机制详解 背1
一.Java异常概述 在Java中,所有的事件都能由类描述,Java中的异常就是由java.lang包下的异常类描述的. Trowable是所有异常的超类. 他的常用方法printStackTrec ...
- Solidity string to uint
oraclize result以string格式返回,solidity没有uint(string)这样的强制转换功能,如果要解析其中的数字,可以用oraclize提供的parseInt方法: prag ...
- 解决IE与FF 中 input focus 光标移动在最后的方案
只要把input元素的id传进来即可 function moveCursor(id) { var id = document.getElementById(id); id.focus(); var ...
- SQLServer跨库查询--分布式查询
出处:http://www.cnblogs.com/doosmile/archive/2012/03/16/2400646.html --用openrowset连接远程SQL或插入数据 --如果只是临 ...
- App测试从入门到精通之App分类和场景操作系统
App概要 APP是application的缩写.通常指的是手机软件上的应用,或称为手机客户端.手机app就是手机的应用程序.随着智能手机的越发普及,用户越发依赖手机软件商品店,app开发的需求与发展 ...
- Fiddler 教程之:Fiddler捕获会话
1 Fiddler的工作原理 Fiddler 是以代理web服务器的形式工作的,它使用代理地址:127.0.0.1,端口:8888.当Fiddler退出的时候它会自动注销,这样就不会影响别的程序.不过 ...
- jqGrid查询案例(实用)
var ThisTime = getNowFormatDate(); //加载表格 function GetGrid() { var selectedRowIndex = 0; var $gridTa ...
- (转)MongoDB入门分享-笔记整理精选
原文地址:http://www.cnblogs.com/Kummy/p/3372729.html 最近在学习MongoDB,怕以后忘记,自己做了一个整理,给不知道的小伙伴一起分享学习一下. 第一步&g ...
- 注入学习1:SQL注入语句大全
学习背景 之前做了xss预防,以及些许的注入预防了,但是不够全面,如果还是搜集了下一些常用的注入手段,以此用来进行更好的预防. 什么是注入 一般来说,SQL注入一般存在于形如:HTTP://xxx.x ...