【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树
题解
orz vfk的题解
3065: 带插入区间K小值 系列题解
惨

一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE)。
后来改成枚举子树元素插入,空间缩小为约 \(\frac 1 4\) ,然而TLE。
然后把替罪羊树的 \(\alpha\) 从 0.6改成0.75,就卡过了。





代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN=140005, MAXM=3e7, MAXB=2e7, MX=70000;
const double al=0.75;
char BUF[MAXB], *cp=BUF;
void rd(int &x){
x=0;
while(*cp<'0'||'9'<*cp)cp++;
while('0'<=*cp&&*cp<='9')x=x*10+*cp++-'0';
}
char rc(){while(*cp<'A'||'Z'<*cp)cp++; return *cp++;}
int N, M, L, R, TOP, top, ov;
int nt, tot, ok, A[MAXN];
struct Seg{
Seg *lc, *rc;
int s;
void *operator new(size_t);
void operator delete(void *);
Seg();
void up(){s=lc->s+rc->s;}
}tr[MAXM], *ST[MAXM], *tmp[MAXN];
void *Seg::operator new(size_t size){return ST[--TOP];}
void Seg::operator delete(void *p){ST[TOP++]=(Seg*)p;}
Seg::Seg(){lc=rc=tr;s=0;}
void dec(Seg *&x){
if(x==tr) return;
dec(x->lc); dec(x->rc); delete(x); x=tr;
}
void upd(Seg *&x, int l, int r, int k, int v){
if(x==tr) x=new Seg;
if(l==r){x->s+=v; return;}
int mid=(l+r)>>1;
if(k<=mid) upd(x->lc,l,mid,k,v);
else upd(x->rc,mid+1,r,k,v);
x->up();
if(!x->s) dec(x);
}
struct Node{
Node *lc, *rc;
Seg *c, *s;
int sz, v;
void up(){sz=1+lc->sz+rc->sz;}
}nd[MAXN], *st[MAXN], *root;
void dfs(Node *x){
if(x==nd) return; dec(x->s);
dfs(x->lc); st[top++]=x; dfs(x->rc);
}
void bu(Node *&x, int l, int r){
if(l>r){x=nd; return;}
int mid=(l+r)>>1; x=st[mid];
bu(x->lc,l,mid-1); bu(x->rc,mid+1,r);
x->up();
for(int i=l; i<=r; ++i) upd(x->s,0,MX,st[i]->v,1);
}
void rebu(Node *&x){top=0; dfs(x); bu(x,0,top-1);}
void ins(Node *&x, int k, int v, int d=0){
if(x==nd){
x=&nd[++tot]; x->v=v;
upd(x->c,0,MX,v,1);
upd(x->s,0,MX,v,1);
return;
}
upd(x->s,0,MX,v,1);
int t=x->lc->sz+1;
if(k<=t){
ins(x->lc,k,v,d+1); x->up();
if(x->lc->sz>=al*x->sz) rebu(x);
}else{
ins(x->rc,k-t,v,d+1); x->up();
if(x->rc->sz>=al*x->sz) rebu(x);
}
}
void md(Node *&x, int k, int v){
if(x==nd) return;
int t=x->lc->sz;
if(k==t+1){
ov=x->v; x->v=v;
dec(x->c); upd(x->c,0,MX,v,1);
}else if(k<=t) md(x->lc,k,v);
else md(x->rc,k-t-1,v);
upd(x->s,0,MX,ov,-1);
upd(x->s,0,MX,v,1);
}
void qry(Node *x, int l, int r){
if(x==nd) return;
if(L<=l&&r<=R){
tmp[nt++]=x->s;
return;
}
int t=x->lc->sz;
if(L<=l+t&&l+t<=R) tmp[nt++]=x->c;
if(L<l+t) qry(x->lc,l,l+t-1);
if(l+t<R) qry(x->rc,l+t+1,r);
}
int kth(int k){
int l=0, r=MX;
while(l<r){
int t=0, mid=(l+r)>>1;
for(int i=0; i<nt; ++i) t+=tmp[i]->lc->s;
if(k<=t){
r=mid;
for(int i=0; i<nt; ++i) tmp[i]=tmp[i]->lc;
}else{
l=mid+1; k-=t;
for(int i=0; i<nt; ++i) tmp[i]=tmp[i]->rc;
}
}
return l;
}
void init(){
tr[0].lc=tr[0].rc=tr;
for(int i=MAXM-1; i>0; --i) ST[TOP++]=tr+i;
root=nd[0].lc=nd[0].rc=nd;
nd[0].c=nd[0].s=tr;
for(int i=1; i<MAXN; ++i){
nd[i].c=nd[i].s=tr;
nd[i].lc=nd[i].rc=nd;
nd[i].sz=1;
}
for(int i=1; i<=N; ++i){
upd(nd[i].c,0,MX,A[i],1);
st[top++]=nd+i; nd[i].v=A[i];
}
bu(root,0,top-1); tot=N;
}
int main(){
fread(BUF, 1, MAXB, stdin);rd(N);
for(int i=1; i<=N; ++i) rd(A[i]);
init(); rd(M);int last=0;
while(M--){
char ch=rc();
int x,y,k; rd(x),rd(y);
x^=last; y^=last;
if(ch=='Q'){
L=x, R=y;
rd(k); k^=last;
nt=0; qry(root,1,N);
printf("%d\n", last=kth(k));
}else if(ch=='M')md(root,x,y);
else if(ch=='I')ins(root,x,y),N++;
}
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小值 (替罪羊树套线段树)
毒瘤题.参考抄自博客:hzwer 第一次写替罪羊树,完全是照着题解写的,发现这玩意儿好强啊,不用旋转每次都重构还能nlognnlognnlogn. 还有外面二分和里面线段树的值域一样,那么r = mi ...
- 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小值.他每次向它的随从伏特提出 ...
随机推荐
- 运维朋友们,别再问需不需要学 Python 了!
运维人员需不需要学开发?需不需要学 Python?PythonN 和 Shell 有什么区别?天天问这种好水的问题,我实在受不了,决定帮大家扫扫盲. 现阶段,掌握一门开发语言已经成为高级运维工程师的必 ...
- 题解 P2955 【[USACO09OCT]奇数偶数Even? Odd? 】
很明显这题是个假入门! 小金羊一不小心点进题解发现了内幕 能看的出来都WA过Unsigned long long int 做题可以用Python,Python的变量虽然 强悍的不行! 但是我们可以用字 ...
- WordPress忘记密码找回登录密码的四种行之有效的方法
WordPress忘记密码找回登录密码的四种行之有效的方法 PS:20170214更新,感谢SuperDoge同学提供的方法,登入phpMyAdmin后,先从左边选自己的数据库,然后点上面的 SQL ...
- 【BZOJ1562】【NOI2009】变换序列(二分图匹配)
[BZOJ1562][NOI2009]变换序列 题面 BZOJ 洛谷 这题面写的是真的丑,还是先手动翻译成人话. 让你构造一个\(0..N-1\)的排列\(T\) 使得\(Dis(i,T_i)\)为给 ...
- 输入三个数a,b,n,输出a和b不大于n的公倍数的个数
题:输入三个数a,b,n,输出a和b不大于n的公倍数的所有个数. 这题的思想是先求得a和b的最大公约数,然后用a和b的积除以最大公约数,得到最小公倍数,再持续加上最小公倍数,直到超过n,记下n的个数. ...
- Codeforces 576D. Flights for Regular Customers(倍增floyd+bitset)
这破题调了我一天...错了一大堆细节T T 首先显然可以将边权先排序,然后逐个加进图中. 加进图后,倍增跑跑看能不能到达n,不能的话加新的边继续跑. 倍增的时候要预处理出h[i]表示转移矩阵的2^0~ ...
- APIO2017
商旅 在广阔的澳大利亚内陆地区长途跋涉后,你孤身一人带着一个背包来到了科巴.你被这个城市发达而美丽的市场所 深深吸引,决定定居于此,做一个商人.科巴有个集市,集市用从1到N的整数编号,集市之间通过M条 ...
- pdf 下载整理
pdf下载整理: using System; using System.Collections.Generic; using System.Linq; using System.Web; using ...
- python学习(十六)写爬虫爬取糗事百科段子
原文链接:爬取糗事百科段子 利用前面学到的文件.正则表达式.urllib的知识,综合运用,爬取糗事百科的段子先用urllib库获取糗事百科热帖第一页的数据.并打开文件进行保存,正好可以熟悉一下之前学过 ...
- discuz开发,登录次数过多,锁定解决方法
到数据库里的表找到pre_common_failedlogin 和pre_ucenter_failedlogins清空里面的内容即可. truncate table pre_common_failed ...