BZOJ-3065 带插入区间K小值
替罪羊树套权值线段树,其中替罪羊树可以满足插入的操作。
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cctype>
#define rep(i, l, r) for(int i=l; i<=r; i++)
#define clr(x, c) memset(x, c, sizeof(x))
#define inf 0x7fffffff
#define ll long long
#define maxn 80010
#define maxl 70010#define l(x) Left[x]
#define r(x) Right[x]
#define s(x) Size[x]
#define k(x) Key[x]
#define t(x) Tree[x]
#define ls(x) Size[Left[x]]
#define rs(x) Size[Right[x]]
#define a 0.8using namespace std;
inline int read()
{int x=0, f=1; char ch=getchar();while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}while (isdigit(ch)) x=x*10+ch-'0', ch=getchar();return x*f;
}//=========================================================================================struct node
{node *l, *r; int sum;node () {sum=0; l=r=NULL;}
} *blank=new(node);
void Add(int l, int r, int k, node*&t)
{if (t==blank) t=new(node), t->l=t->r=blank;t->sum++;if (l==r) return; int mid=(l+r)>>1;if (k<=mid) Add(l, mid, k, t->l); else Add(mid+1, r, k, t->r);
}
void Del(int l, int r, int k, node*&t)
{t->sum--;if (l==r) return; int mid=(l+r)>>1;if (k<=mid) Del(l, mid, k, t->l); else Del(mid+1, r, k, t->r);
}//=========================================================================================int Left[maxn], Right[maxn], Key[maxn], Size[maxn], V=0, roof, dfn[maxn], top;
node *Tree[maxn];
void Build(int l, int r, int &t)
{if (l>r) {t=0; return;}int mid=(l+r)>>1; t=dfn[mid], t(t)=blank, s(t)=r-l+1;rep(i, l, r) Add(0, maxl, k(dfn[i]), t(t));Build(l, mid-1, l(t)), Build(mid+1, r, r(t));
}
node *range[maxn];
int p[maxn], nr, np;
void ranging(int l, int r, int t) //BST查找区间
{if (r<ls(t)) ranging(l, r, l(t)); //全在左边else if (l>ls(t)) ranging(l-ls(t)-1, r-ls(t)-1, r(t)); //全在右边else if (!l && r==s(t)-1) range[++nr]=t(t); //整棵树都是else //分跨两边{p[++np]=k(t);if (l<ls(t)) ranging(l, ls(t)-1, l(t));if (r>ls(t)) ranging(0, r-ls(t)-1, r(t));}
}
void getrange(int l, int r){nr=np=0; ranging(l-1, r-1, roof);}
void dfs(int t){if (l(t)) dfs(l(t)); dfn[++top]=t; if (r(t)) dfs(r(t));} //DFS序
void Recycle(node *t) //回收节点
{if (!t->sum) return;if (t->l) Recycle(t->l);if (t->r) Recycle(t->r);delete(t);
}
void reBuild(int &t)
{top=0; dfs(t); rep(i, 1, top) Recycle(t(dfn[i])); Build(1, top, t);
}//=========================================================================================bool Insert(int r, int k, int h, int &t)
{if (!t){t=++V;s(t)=1, k(t)=k, l(t)=r(t)=0, t(t)=blank;Add(0, maxl, k, t(t));return h>log(V)/log(1/a);}bool flag;if (r<=ls(t)) flag=Insert(r, k, h+1, l(t));else flag=Insert(r-ls(t)-1, k, h+1, r(t));s(t)=ls(t)+rs(t)+1; Add(0, maxl, k, t(t));if (flag && (max(ls(t), rs(t)) > a*s(t))) {reBuild(t); return false;}return flag;
}
int Change(int r, int k, int t)
{if (ls(t)==r){int v=k(t);Del(0, maxl, k(t), t(t));Add(0, maxl, k(t)=k, t(t));return v;}int v;if (r<ls(t)) v=Change(r, k, l(t));else v=Change(r-ls(t)-1, k, r(t));Del(0, maxl, v, t(t));Add(0, maxl, k, t(t));return v;
}
int Query(int l, int r, int rank)
{rank--;getrange(l, r);int L=0, R=maxl;while (L<R){int mid=(L+R)>>1, sum=0;rep(i, 1, nr) sum+=range[i]->l->sum;rep(i, 1, np) sum+=(p[i]>=L && p[i]<=mid) ? 1 : 0;if (rank<sum){rep(i, 1, nr) range[i]=range[i]->l; R=mid;}else{rank-=sum; rep(i, 1, nr) range[i]=range[i]->r; L=mid+1;}}return L;
}//=========================================================================================int n, m, w[maxn], last=0;
int main()
{blank->l=blank->r=blank;n=read(); rep(i, 1, n) w[i]=read();l(0)=r(0)=s(0)=0;rep(i, 1, n) dfn[i]=++V, k(V)=w[i];Build(1, n, roof);m=read();while (m--){char ch=getchar(); while (ch!='Q' && ch!='M' && ch!='I') ch=getchar();if (ch=='Q'){int x=read()^last, y=read()^last, z=read()^last;printf("%d\n", last=Query(x, y, z));}else if (ch=='I'){int x=read()^last, y=read()^last;Insert(x-1, y, 0, roof);}else{int x=read()^last, y=read()^last;Change(x-1, y, roof);}}return 0;
}
转载于:https://www.cnblogs.com/NanoApe/p/4480118.html
BZOJ-3065 带插入区间K小值相关推荐
- 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树
题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...
- P4278 带插入区间K小值
题目链接 题目描述 快捷版题意:带插入.修改的区间k小值在线查询. 输入格式 第一行一个正整数nnn,表示原来有nnn只跳蚤排成一行做早操. 第二行有nnn个用空格隔开的非负整数,从左至右代表每只跳蚤 ...
- 【bzoj3065】: 带插入区间K小值 详解——替罪羊套函数式线段树
不得不说,做过最爽的树套树---- 由于有了区间操作,我们很容易把区间看成一棵平衡树,对他进行插入,那么外面一层就是平衡树了,这就与我们之前所见到的不同了.我们之前所见到的大多数是线段树套平衡树而此题 ...
- 【luogu3834】【模板】可持久化线段树 2(主席树),静态区间第K小值
problem solution 题目:有n个数,多次询问一个区间[L,R]中第k小的值是多少. 思路: 查询[1,n]中的第k小值: 先对数据进行离散化,然后按值域建立线段树,线段树中维护某个值域中 ...
- hdu 2665(主席树查询区间k大值)
先贴我自己写的代码做模板虽然跟原博主没什么两样.(一开始空间开的4*maxn,交到hdu上一直TLE很奇怪) #include<bits/stdc++.h> using namespace ...
- 4923: [Lydsy1706月赛]K小值查询 平衡树 非旋转Treap
国际惯例的题面: 这种维护排序序列,严格大于的进行操作的题都很套路...... 我们按照[0,k],(k,2k],(2k,inf)分类讨论一下就好. 显然第一个区间的不会变化,第二个区间的会被平移进第 ...
- HDU3949 XOR (线性基、查找第k小值)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 我们用高斯消元求出的a1,a2,-,ana_1,a_2, \dots,a_na1,a2,-,an ...
- 【HDU3949 + BZOJ2115 + CF724G】【异或线性基例题】| 倍增 | 第k小异或和 | DFS处理环 |【CGWR】| N
三道关于异或线性基的有趣的题目 [1] HDU 3949. XOR Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/3276 ...
- COGS-930-找第k小的数-HNOI2012-主席树
描述 静态区间第k小值 分析 改了一个主席树的模板, 改成了数组版. 感觉数组的要简洁好多. 主席树的讲解:http://hi.baidu.com/lov_zyf/item/87b578342e73f ...
最新文章
- Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
- 一起学nRF51xx 11 - ficr
- vs2015 编译时错误列表中没有错误,dll却没有生成出来
- 一道微软公司的面试题目的算法实现
- 315. Count of Smaller Numbers After Self 计算右侧小于当前元素的个数
- SecureCRT同时向多个终端发送命令
- Koa nuxt最佳实践前篇
- iOS中POST请求
- 阿里云 云服务器ECS(CentOS 8.0 64位) 安装 MySQL 数据库
- Bailian4029 数字反转【进制】(POJ NOI0105-29)
- c 11 主要的新语言特性,C 11系列
- ubuntu opencv 安装
- SIM900A发送数据到新浪云服务器
- c语言hypot函数,hypot ( )【C语言库函数源代码】
- c语言编程一个数的质子求出来,量子力学第一章课外练习题
- DCDC--Burst Mode和Pulse Skipping Mode
- 什么是最好的在线UML软件工具?
- 怎么设置计算机自己休眠断网,win10系统怎么设置待机断网 待机断网设置方法
- Shader学习3——半兰伯特
- 干货分享:Totoro 在自动化测试领域的深耕与收获
热门文章
- 自己打造Sublime Text 3 开发编辑神器
- java缓存技术选型,重难点整理
- python【力扣LeetCode算法题库】26-删除排序数组中的重复项
- 免费使用谷歌GPU训练神经网络
- 没有java home_【Java安装】必须有JAVA_HOME变量吗
- 智能网联技术 英文_智能网联技术是什么?有什么好推荐学习地方?
- 网络推广营销之网站优化选择优质友情链接的标准
- dba用什么工具连接mysql_DBA必备的15款MySQL管理工具
- 网页html是什么语言程序,html是什么
- linux函数怎么判断文件已更改,Linux下使用md5sum查看文件及程序是否被修改