3065: 带插入区间K小值_树套树_替罪羊树_权值线段树
经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题.
Code:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
// 带插入区间 k 小值
// 外层:替罪羊
// 内层:权值线段树
using namespace std;
#define setIO(s) freopen(s".in","r",stdin), freopen(s".out","w",stdout)
#define debug() printf("OK\n")
#define maxn 11005000
#define N 70002
int n,lastans;
struct Segment_Tree{
struct Node{
int ls,rs,siz;
Node(int ls=0,int rs=0,int siz=0):ls(ls),rs(rs),siz(siz){}
}node[maxn];
queue<int>Q;
void init(){ for(int i=1;i<maxn;++i) Q.push(i); }
void newnode(int &o) { o=Q.front(), Q.pop(); }
void update(int l,int r,int &o,int pos,int delta){
if(!o) newnode(o);
node[o].siz+=delta;
if(!node[o].siz) { dfs(o); return; }
if(l==r) return;
int mid=(l+r)>>1;
if(pos<=mid) update(l,mid,node[o].ls,pos,delta);
else update(mid+1,r,node[o].rs,pos,delta);
}
void dfs(int &o){
if(!o)return;
dfs(node[o].ls),Q.push(o),dfs(node[o].rs);
node[o].siz=0;
o=0;
}
}segin;
struct Binary_Search_Tree{
inline bool check(int son,int o){
if(son*10>=o*9) return true;
return false;
}
int cnt,root;
int seq[N],count[3];
vector<int>re;
struct Node{
int ls,rs,siz,root,cur,val;
Node(int ls=0,int rs=0,int siz=0,int root=0,int cur=0,int val=0):ls(ls),rs(rs),root(root),cur(cur),val(val){}
}node[maxn];
inline void newnode(int &o,int val){ o=++cnt,node[o].val=val,node[o].siz=1; }
void dfs(int &o){
if(!o) return;
segin.dfs(node[o].root),segin.dfs(node[o].cur);
dfs(node[o].ls),re.push_back(o),dfs(node[o].rs);
node[o].siz=0;
o=0; }
void construct(int l,int r,int &o){
if(l>r)return;
int mid=(l+r)>>1;
o=re[mid]; for(int i=l;i<=r;++i)
segin.update(0,N,node[o].root,node[re[i]].val,1); segin.update(0,N,node[o].cur,node[o].val,1);
if(l==r){ node[o].siz=1; return; } construct(l,mid-1,node[o].ls), construct(mid+1,r,node[o].rs);
node[o].siz=node[node[o].ls].siz+node[node[o].rs].siz+1;
}
inline void Rebuild(int &o){ re.clear(),dfs(o),construct(0,re.size()-1,o); }
void insert(int &o,int k,int val,bool is){
if(!o){
newnode(o,val),segin.update(0,N,node[o].root,val,1),segin.update(0,N,node[o].cur,val,1);
return;
}
++node[o].siz, segin.update(0,N,node[o].root,val,1);
bool tag;
if(k<=node[node[o].ls].siz+1) tag=check(node[node[o].ls].siz+1,node[o].siz), insert(node[o].ls,k,val,is||tag);
else tag=check(node[node[o].rs].siz+1,node[o].siz), insert(node[o].rs,k-node[node[o].ls].siz-1,val,is||tag);
if(!is&&tag) Rebuild(o);
}
int modify(int o,int pos,int delta){
int num;
if(pos==node[node[o].ls].siz+1) {
segin.update(0,N,node[o].root,node[o].val,-1),segin.dfs(node[o].cur),node[o].cur=0;
segin.update(0,N,node[o].root,delta,1),segin.update(0,N,node[o].cur,delta,1);
num=node[o].val,node[o].val=delta;
return num;
}
if(pos<=node[node[o].ls].siz) num=modify(node[o].ls,pos,delta);
else num=modify(node[o].rs,pos-node[node[o].ls].siz-1,delta);
segin.update(0,N,node[o].root,num,-1),segin.update(0,N,node[o].root,delta,1);
return num;
}
void Build(){
scanf("%d",&n),re.clear();
int tmp,x ;
for(int i=1;i<=n;++i)
scanf("%d",&tmp),newnode(x,tmp),re.push_back(x);
construct(0,re.size()-1,root);
}
void Get(int l,int r,int o,int L,int R){
if(l>R||r<L||l>r||!o)return;
if(l>=L&&r<=R) { seq[++count[0]]=node[o].root; return; }
int mid=node[node[o].ls].siz+l;
if(mid>=L&&mid<=R&&mid<=r) seq[++count[0]]=node[o].cur;
Get(l,mid-1,node[o].ls,L,R),Get(mid+1,r,node[o].rs,L,R);
}
int solve(int l,int r,int k){
if(l==r) return l;
int lsum=0;
for(int i=1;i<=count[0];++i) {
lsum+=segin.node[segin.node[seq[i]].ls].siz;
}
int mid=(l+r)>>1;
if(k>lsum)
{
for(int i=1;i<=count[0];++i) seq[i]=segin.node[seq[i]].rs;
return solve(mid+1,r,k-lsum);
}
else
{
for(int i=1;i<=count[0];++i)seq[i]=segin.node[seq[i]].ls;
return solve(l,mid,k);
}
}
void Insert(){
int a,b;
++n,scanf("%d%d",&a,&b),a^=lastans,b^=lastans,insert(root,a,b,0);
}
void Modify(){
int a,b;
scanf("%d%d",&a,&b),a^=lastans,b^=lastans,modify(root,a,b);
}
int Query(){
int L,R,k;
count[0]=0, scanf("%d%d%d",&L,&R,&k),L^=lastans,R^=lastans,k^=lastans;
if(L>R)swap(L,R);
Get(1,n,root,L,R);
return solve(0,N,k);
}
}BST;
int main(){
//setIO("input");
segin.init(), BST.Build();
char opt[10];
int q;
scanf("%d",&q);
while(q--){
scanf("%s",opt);
if(opt[0]=='I') BST.Insert();
if(opt[0]=='M') BST.Modify();
if(opt[0]=='Q') printf("%d\n",lastans=BST.Query());
}
return 0;
}
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小值
http://www.lydsy.com/JudgeOnline/problem.php?id=3065 题意:带插入.修改的区间k小值在线查询.(原序列n<=35000, 询问<=175 ...
- bzoj 3065: 带插入区间K小值(分块)
Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它 ...
- BZOJ 3065 带插入区间K小值
http://www.lydsy.com/JudgeOnline/problem.php?id=3065 思路:替罪羊树套权值线段树. 当替罪羊树某个子树大于某个比利(比例)时就暴力重构,本题时间复杂 ...
- BZOJ 3065 带插入区间K小值 (替罪羊树套线段树)
毒瘤题.参考抄自博客:hzwer 第一次写替罪羊树,完全是照着题解写的,发现这玩意儿好强啊,不用旋转每次都重构还能nlognnlognnlogn. 还有外面二分和里面线段树的值域一样,那么r = mi ...
- 【学习笔记】浅析平衡树套线段树 & 带插入区间K小值
常见的树套树 一般来说,在嵌套数据结构中,线段树多被作为外层结构使用. 但线段树毕竟是 静态 的结构,导致了一些不便. 下面是一个难以维护的例子: 带插入区间 \(k\) 小值问题 来源:Luogu ...
- [BZOJ3065]带插入区间K小值 解题报告 替罪羊树+值域线段树
刚了一天的题终于切掉了,数据结构题的代码真**难调,这是我做过的第一道树套树题,做完后感觉对树套树都有阴影了......下面写一下做题记录. Portal Gun:[BZOJ3065]带插入区间k小值 ...
随机推荐
- 超便携式截屏录屏软件FastStone Capture
超便携式截屏录屏软件FastStone Capture
- Scala语言
一.Scala概述 Scala简介 Scala是一种针对JVM将函数和面向对象技术组合在一起的编程语言.所以Scala必须要有JVM才能运行,和Python一样,Scala也是可以面向对象和面向函数的 ...
- Redis-1-安装
Redis-1-安装 标签(空格分隔): linux,redis 下载 cd /usr/local/src/ wget http://download.redis.io/releases/redis- ...
- 新型查询系统impala
这羊头很酷... Apache Impala是Apache Hadoop的开源本地分析数据库.Impala由Cloudera,MapR,Oracle和Amazon提供. 在Hadoop上进行BI风格的 ...
- C#如何生成一个随机种子for Random?
就这么写: Random rand = new Random((int)DateTime.Now.Ticks); 或者这么写: Random rand = new Random(new Guid(). ...
- 前端模块化 | 解读JS模块化开发中的 require、import 和 export
本篇分为两个部分 第一部分:总结了ES6出现之前,在当时现有的运行环境中,实现"模块"的方式: 第二部分:总结了ES6出现后,module成为ES6标准,客户端实现模块化的解决方案 ...
- Android TextView加上阴影效果
<TextView android:id="@+id/test_shadow" android:layout_width="wrap_content" a ...
- Servlet学习(四)——response
1.概述 在创建Servlet时会覆盖service()方法,或doGet()或doPost(),这些方法都有两个参数,一个是代表请求的request和代表响应response. service方法中 ...
- 影像服务——加载CESIUM自带的影像服务
1.加载arcgis数据——ArcGisMapServerImageryProvider var viewer = new Cesium.Viewer("cesiumDiv",{ ...
- Oracle with as 嵌套
oracle with as可以理解为临时视图,可以极大的简化sql语句,并且支持嵌套使用. With c3 As(Select * From v_tr_daily Where p_date=to_ ...