BZOJ 3065 带插入区间K小值 (替罪羊树套线段树)
毒瘤题.参考抄自博客:hzwer
- 第一次写替罪羊树,完全是照着题解写的,发现这玩意儿好强啊,不用旋转每次都重构还能nlognnlognnlogn.
- 还有外面二分和里面线段树的值域一样,那么r = mid就相当于线段树往左儿子走,l = mid + 1就相当于线段树往右儿子走,神了.(这样的话就有点像决策始终一致的整体二分了口胡).
CODE
TIP:TIP:TIP: 参考博客的代码92行应该是小写的"r>L+1"…不过都能过.
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
char ch; for(;!isdigit(ch=getc()););
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}
const int MAXN = 70005; //N+Q最大值
const int MAXV = 70000; //权值最大值
const int MAXNN = 10000005; //线段树结点
const double alpha = 0.75;
int n, q, root, tmp, sz;
int v[MAXN], num[MAXN], rt[MAXN], ch[MAXN][2];
struct seg{ int ls, rs, sum; }a[MAXNN];
vector<int> rec, p, t;
inline int newnode() {
if(!rec.size()) return ++sz;
int o = rec.back(); rec.pop_back();
return o;
}
void reclaim(int &i) { //seg
if(!i) return;
rec.push_back(i);
reclaim(a[i].ls), reclaim(a[i].rs);
a[i].sum = 0;
i = 0; //注意顺序!
}
void del(int &i) { //sgt
if(!i) return; reclaim(rt[i]);
del(ch[i][0]); p.push_back(i); del(ch[i][1]);
i = 0;
}
void insert(int &i, int l, int r, int x, int val) {
if(!i) i = newnode();
if(l == r) { a[i].sum += val; return; }
int mid = (l + r) >> 1;
if(x <= mid) insert(a[i].ls, l, mid, x, val);
else insert(a[i].rs, mid+1, r, x, val);
a[i].sum = a[a[i].ls].sum + a[a[i].rs].sum;
if(!a[i].sum) reclaim(i);
}
void build(int &i, int l, int r) {
if(l > r) return;
if(l == r) { i = num[l]; insert(rt[i], 0, MAXV, v[i], 1); return; }
int mid = (l + r) >> 1; i = num[mid];
build(ch[i][0], l, mid-1);
build(ch[i][1], mid+1, r);
for(int j = l; j <= r; ++j)
insert(rt[i], 0, MAXV, v[num[j]], 1);
}
inline void rebuild(int &i) {
del(i); int siz = p.size();
for(int l = 1; l <= siz; ++l) num[l] = p[l-1];
build(i, 1, siz); p.clear();
}
int Modify(int i, int x, int val) {
insert(rt[i], 0, MAXV, val, 1);
int ret, L = a[rt[ch[i][0]]].sum;
if(L + 1 == x) { ret = v[i]; v[i] = val; }
else if(L >= x) ret = Modify(ch[i][0], x, val);
else ret = Modify(ch[i][1], x-L-1, val);
insert(rt[i], 0, MAXV, ret, -1);
return ret;
}
void Insert(int &i, int x, int val) {
if(!i) { i = ++n; insert(rt[i], 0, MAXV, val, 1); v[i] = val; return; }
insert(rt[i], 0, MAXV, val, 1);
int L = a[rt[ch[i][0]]].sum;
if(L >= x) Insert(ch[i][0], x, val);
else Insert(ch[i][1], x-L-1, val);
if(a[rt[i]].sum * alpha > max(a[rt[ch[i][0]]].sum, a[rt[ch[i][1]]].sum)) {
if(tmp) {
if(ch[i][0] == tmp) rebuild(ch[i][0]);
else rebuild(ch[i][1]); tmp = 0;
}
}
else tmp = i;
}
void query(int i, int l, int r) {
int L = a[rt[ch[i][0]]].sum, Size = a[rt[i]].sum;
if(l == 1 && r == Size) { t.push_back(rt[i]); return; }
if(l <= L+1 && r >= L+1) p.push_back(v[i]);
if(r <= L) query(ch[i][0], l, r);
else if(l > L+1) query(ch[i][1], l-L-1, r-L-1);
else {
if(l <= L) query(ch[i][0], l, L);
if(r > L+1) query(ch[i][1], 1, r-L-1);
}
}
inline int Query(int L, int R, int K) {
query(root, L, R);
int l = 0, r = 70000, sizt = t.size(), sizp = p.size();
while(l < r) {
int mid = (l + r) >> 1, tot = 0;
for(int i = 0; i < sizt; ++i) tot += a[a[t[i]].ls].sum;
for(int i = 0; i < sizp; ++i) if(p[i] >= l && p[i] <= mid) ++tot;
if(K <= tot) {
for(int i = 0; i < sizt; ++i) t[i] = a[t[i]].ls;
r = mid;
}
else {
for(int i = 0; i < sizt; ++i) t[i] = a[t[i]].rs;
l = mid+1; K -= tot;
}
}
t.clear(); p.clear(); return l;
}
int main () {
read(n);
for(int i = 1; i <= n; ++i)
read(v[i]), num[i] = i;
build(root, 1, n);
read(q);
char s[2]; int x, y, K, lastans = 0;
while(q--) {
while(!isalpha(s[0]=getc()));
while(isalpha(s[1]=getc()));
read(x), read(y);
x ^= lastans, y ^= lastans;
if(s[0] == 'Q') read(K), K ^= lastans, printf("%d\n", lastans=Query(x, y, K));
else if(s[0] == 'M') Modify(root, x, y);
else {
tmp = 0; Insert(root, x-1, y); if(tmp) rebuild(root);
}
}
return 0;
}
BZOJ 3065 带插入区间K小值 (替罪羊树套线段树)的更多相关文章
- bzoj 3065: 带插入区间K小值 替罪羊树 && AC300
3065: 带插入区间K小值 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 1062 Solved: 253[Submit][Status] Des ...
- 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树
题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...
- BZOJ 3065 带插入区间K小值(sag套线段树)
3065: 带插入区间K小值 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 4696 Solved: 1527[Submit][Status][Di ...
- bzoj 3065: 带插入区间K小值(分块)
Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它 ...
- BZOJ 3065 带插入区间K小值
http://www.lydsy.com/JudgeOnline/problem.php?id=3065 思路:替罪羊树套权值线段树. 当替罪羊树某个子树大于某个比利(比例)时就暴力重构,本题时间复杂 ...
- 3065: 带插入区间K小值_树套树_替罪羊树_权值线段树
经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题. Code: #include <cstdio> #include <algorit ...
- 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树
[BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...
- 【BZOJ】3065: 带插入区间K小值
http://www.lydsy.com/JudgeOnline/problem.php?id=3065 题意:带插入.修改的区间k小值在线查询.(原序列n<=35000, 询问<=175 ...
- 【bzoj3065】带插入区间K小值 替罪羊树套权值线段树
题目描述 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它的随从伏特提出 ...
随机推荐
- 【转载】在一台电脑上运行两个或两个以上的tomcat
作者注: 本片为转载文章,一台电脑运行两个及以上tomcat的原因是:第一个eclipse版本是4.5,最高支持tomcat8.0版本,并且这个版本的eclipse通过svn提交和更新项目极其缓慢,无 ...
- 基于docker的mongodb安装以及PHP使用
说明:用docker基于单服务器,虚拟多个服务器的方案, 以下是两个config服务器,两个分片,以及每个分片有一个副本的方案 这里关于给mongodb设置远程密码的问题,我采取了用两个compser ...
- 13.lsof恢复删除的文件
[root@temp ~]# lsof -p 5643COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEoracle 5643 ...
- 二、python数据类型、字符编码、文件处理
一. 前言 1. 什么是数据: x = 10,10就是我们要存储的数据 2. 为何数据要分不同的类型 数据是用来表示状态的, 不同的状态就应该用不同类型的数据去表示 3. 数据类型 数字(整型.长整型 ...
- Spring实战(三)Spring中装配Bean的三种方式---XML、JavaConfig、AutoWire
创建应用对象之间协作关系的行为称为装配(wiring),这也是依赖注入的本质. Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系,而开发者需要告诉Spring需要创建哪些 ...
- HTTP协议探究(四):TCP和TLS优化
一 复习与目标 1 复习 简单密码学.对称加密与非对称加密 数字签名.数字证书 SSL/TLS HTTPS = HTTP + SSL/TLS,SSL/TLS为HTTP提供了保密性.完整性和鉴别性 2 ...
- linux 安装redis 完整步骤
最近在linux服务器上需要安装redis,来存放数据,增加用户访问数据的速度,由于是第一次安装,于是在百度上搜了一篇文章,按照这篇博客,顺利安装好了,因此将博主的文章拷过来记录一下,方便以后使用,也 ...
- ASP .NET依赖注入理解
ASP .NET依赖注入理解[转]: https://www.cnblogs.com/wzk153/p/10892444.html
- Boost,Eigen,Flann—C++标准库预备役
Boost,Eigen,Flann—C++标准库预备役 第一预备役:Boost Boost库是为C++语言标准库提供扩展的一些C++程序库的总称. Boost库由Boost社区组织开发.维护 ...
- VBA精彩代码分享-3
在开发VBA程序中,我们可能会需要用代码处理VBA工程,包括启用VBA工程访问,启用所有宏,动态插入代码,动态删除代码,动态添加引用和自动创建模块等等,本次的分享内容便以这些为主. 启用VBA工程访问 ...