
[BZOJ3065]带插入区间K小值
发布日期:2021-05-07 01:01:57
浏览次数:24
分类:原创文章
本文共 4143 字,大约阅读时间需要 13 分钟。
题目
题目概要
- 询问一个区间的第 k k k 小值。
- 修改一个数。
- 插入一个数。
数据范围与约定
- 原序列长度 N ≤ 3.5 × 1 0 4 N\le 3.5\times 10^4 N≤3.5×104 。
- 插入的数字个数 ≤ 3.5 × 1 0 4 \le 3.5\times 10^4 ≤3.5×104 。
- 修改操作与询问操作均不超过 7 × 1 0 4 7\times 10^4 7×104 次。
- 数字大小总是一个不超过 7 × 1 0 4 7\times 10^4 7×104 的自然数。
强制在线。
思路
解决区间第 k k k 大靠什么?划分树。当然,也可以是权值线段树。
带修改怎么办?划分树中 t o L toL toL 数组用平衡树维护就行了。
划分树自身可能不平衡,套一个替罪羊即可(子树大小为 x x x 时,一共有 2 x 2x 2x 个数字,不会让复杂度变劣)。
复杂度 O ( n log 2 n ) \mathcal O(n\log ^2n) O(nlog2n) 。如果你比较懒(像我一样),就可以把外层改成权值线段树,复杂度 O ( n log n log V ) \mathcal O(n\log n\log V) O(nlognlogV) 。
代码
注意权值可以为零。
#include <cstdio>#include <iostream>#include <cstring>#include <cstdlib>using namespace std;# define rep(i,a,b) for(int i=(a); i<=(b); ++i)inline int readint(){ int a = 0; char c = getchar(), f = 1; for(; c<'0'||c>'9'; c=getchar()) if(c == '-') f = -f; for(; '0'<=c&&c<='9'; c=getchar()) a = (a<<3)+(a<<1)+(c^48); return a*f;}namespace Treap{ const int MaxN = 5000005; int son[MaxN][2], siz[MaxN]; int val[MaxN], data[MaxN]; int cntNode, prio[MaxN]; inline int newNode(int v){ int &id = ++ cntNode; son[id][0] = son[id][1] = 0; data[id] = val[id] = v; prio[id] = (rand()<<16)|rand(); siz[id] = 1; return id; } void pushUp(int o){ val[o] = val[son[o][0]]+ val[son[o][1]]+data[o]; siz[o] = siz[son[o][0]]+ siz[son[o][1]]+1; } struct PII{ int first, second; PII(){ } PII(int F,int S){ first = F, second = S; } int& operator[](const int &x){ return x ? second : first; } }; PII split(int o,int k){ PII p; if(!o) return PII(o,o); if(k <= siz[son[o][0]]){ p = split(son[o][0],k); son[o][0] = p[1], p[1] = o; } else{ k -= siz[son[o][0]]; p = split(son[o][1],k-1); son[o][1] = p[0], p[0] = o; } pushUp(o); return p; } int merge(int a,int b){ if(!a || !b) return a^b; if(prio[a] > prio[b]){ son[a][1] = merge(son[a][1],b); pushUp(a); return a; } else{ son[b][0] = merge(a,son[b][0]); pushUp(b); return b; } }}using namespace Treap;struct treap{ int rt; treap(){ rt = 0; } /* insert x after k-th element */ void insert(int k,int x){ PII p = split(rt,k); p[0] = merge(p[0],newNode(x)); rt = merge(p[0],p[1]); } /* erase k-th element */ void erase(int k){ PII pl = split(rt,k-1); rt = merge(pl[0],split(pl[1],1).second); } int find(int k){ PII pl = split(rt,k-1); PII pr = split(pl[1],1); int res = data[pr[0]]; rt = merge(pl[0],merge(pr[0],pr[1])); return res; } int query(int k){ PII p = split(rt,k); int res = val[p[0]]; rt = merge(p[0],p[1]); return res; }};const int MaxM = 70005;namespace SgTree{ treap tre[MaxM<<1|1]; # define __index(l,r) (((l)+(r))|1) /* insert v after x-th element */ void insert(int x,int v,int l=0,int r=MaxM){ if(l == r) return ; // leaf int id = __index(l,r); int p = tre[id].query(x); if(v <= ((l+r)>>1)){ insert(p,v,l,(l+r)>>1); tre[id].insert(x,1); } else{ insert(x-p,v,(l+r)/2+1,r); tre[id].insert(x,0); } } /* erase x-th element whose value = v */ void erase(int x,int v,int l=0,int r=MaxM){ if(l == r) return ; int id = __index(l,r); int p = tre[id].query(x-1); if(v <= ((l+r)>>1)) erase(p+1,v,l,(l+r)>>1); else erase(x-p,v,(l+r)/2+1,r); tre[id].erase(x); // always do it } /* k-th smallest element in range [ql,qr] */ int query(int ql,int qr,int k,int l=0,int r=MaxM){ if(l == r) return l; int id = __index(l,r); int pl = tre[id].query(ql-1); int pr = tre[id].query(qr); if(pr-pl >= k) // in left part return query(pl+1,pr,k,l,(l+r)>>1); k -= (pr-pl); pl = ql-pl; pr = qr-pr; return query(pl,pr,k,(l+r)/2+1,r); } # undef __index}treap ori; char opt[10];int main(){ srand(5201314); int n = readint(); for(int i=0,v; i<n; ++i){ v = readint(); ori.insert(i,v); SgTree::insert(i,v); } int q = readint(); for(int x,y,ans=0; q; --q){ scanf("%s",opt); x = readint()^ans; y = readint()^ans; if(*opt == 'I'){ SgTree::insert(x-1,y); ori.insert(x-1,y); } if(*opt == 'M'){ SgTree::erase(x,ori.find(x)); SgTree::insert(x-1,y); ori.erase(x); ori.insert(x-1,y); } if(*opt == 'Q'){ ans = SgTree::query(x,y,readint()^ans); printf("%d\n",ans); } } return 0;}
发表评论
最新留言
关注你微信了!
[***.104.42.241]2025年03月28日 15时12分29秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
glob模块
2021-05-08
6 个 Linux 运维典型问题
2021-05-08
oracle无法启动asm实例记录
2021-05-08
取消vim打开文件全是黄色方法
2021-05-08
一个系统部署多个tomcat实例
2021-05-08
HP服务器设置iLO
2021-05-08
从头实现一个WPF条形图
2021-05-08
.NET CORE(C#) WPF 方便的实现用户控件切换(祝大家新年快乐)
2021-05-08
使用QT实现一个简单的登陆对话框(纯代码实现C++)
2021-05-08
QT :warning LNK4042: 对象被多次指定;已忽略多余的指定
2021-05-08
GLFW 源码 下载-编译-使用/GLAD配置
2021-05-08
针对单个网站的渗透思路
2021-05-08
Typescript 学习笔记六:接口
2021-05-08
【ASP.NET】ASP.NET中权限验证使用OnAuthorization实现
2021-05-08
02、MySQL—数据库基本操作
2021-05-08
OpenJDK1.8.0 源码解析————HashMap的实现(一)
2021-05-08
MySQL-时区导致的时间前后端不一致
2021-05-08
2021-04-05阅读小笔记:局部性原理
2021-05-08
go语言简单介绍,增强了解
2021-05-08