BZOJ3065: 带插入区间K小值(替罪羊树+权值线段树)
来源:互联网 发布:单簧管 笛头 知乎 编辑:程序博客网 时间:2024/05/19 09:15
传送门
题意:
带插入区间K小值
题解:
替罪羊树+权值线段树,替罪羊的每一个节点维护子树的权值线段树,暴力重建即可。
每次插入复杂度
#include<bits/stdc++.h>using namespace std;struct IO{ streambuf *ib,*ob; inline void init(){ ios::sync_with_stdio(false); cin.tie(NULL),cout.tie(NULL); ib=cin.rdbuf();ob=cout.rdbuf(); } inline int read(){ char ch=ib->sbumpc();int i=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();} while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();} return i*f; } inline void W(int x){ static int buf[50]; if(!x){ob->sputc('0');ob->sputc('\n');return;} if(x<0){ob->sputc('-');x=-x;} while(x){buf[++buf[0]]=x%10;x/=10;} while(buf[0]) {ob->sputc(buf[buf[0]--]+'0');} ob->sputc('\n'); }}io;const int Maxn=2e5+50;int n,lastans;struct node2{ node2 *lc,*rc; int sze; inline void upt(){ sze=lc->sze+rc->sze; }}Pool2[Maxn<<5],*pool2=Pool2,*null2=Pool2;node2* recyclepool2[Maxn<<5];int tail2=0;inline node2* newnode2(){ node2* tmp=(tail2)?(recyclepool2[tail2--]):(++pool2); tmp->lc=tmp->rc=null2; tmp->sze=0; return tmp;}inline void insert2(node2*& now,int l,int r,int val,int bz=1){ if(l==r){if(now==null2)now=newnode2();now->sze+=bz;return;} if(now==null2)now=newnode2(); int mid=(l+r)>>1; if(val<=mid)insert2(now->lc,l,mid,val,bz); else insert2(now->rc,mid+1,r,val,bz); now->upt();}struct node1{ node1 *lc,*rc; node2 *rt; int val,sze,exi; inline void upt(){ sze=lc->sze+rc->sze+exi; }}Pool1[Maxn],*pool1=Pool1,*null1=Pool1;node1* recyclepool1[Maxn];int tail1=0;inline node1* newnode1(int val){ node1* tmp=((tail1)?(recyclepool1[tail1--]):(++pool1)); tmp->lc=tmp->rc=null1; tmp->sze=tmp->exi=1;tmp->val=val; tmp->rt=null2; return tmp;}inline void recyclenode2(node2*& now){ if(now==null2)return; recyclepool2[++tail2]=now; if(now->lc!=null2)recyclenode2(now->lc); if(now->rc!=null2)recyclenode2(now->rc); now=null2;}int a[Maxn],tot;inline void recyclenode1(node1*& now,int *a){ if(now==null1)return; recyclenode2(now->rt); recyclepool1[++tail1]=now; if(now->lc!=null1)recyclenode1(now->lc,a); if(now->exi)a[++tot]=now->val; if(now->rc!=null1)recyclenode1(now->rc,a); now=null1;}inline int query2(node2* now,int l,int r,int val){ if(val<l||val>r||now==null2)return 0; if(r<=val)return now->sze; int mid=(l+r)>>1; if(val<=mid)return query2(now->lc,l,mid,val); else return now->lc->sze+query2(now->rc,mid+1,r,val);}const int alpha=70;struct ScapeGoatTree{ node1* rt; node2* que[Maxn]; int t[Maxn],tmp,tail; ScapeGoatTree():rt(null1){} inline void build(node1*& now,int *a,int l,int r){ int mid=(l+r)>>1; now=newnode1(a[mid]); for(int i=l;i<=r;i++)insert2(now->rt,0,Maxn-1,a[i]); if(l==r)return; if(l<mid)build(now->lc,a,l,mid-1); if(mid<r)build(now->rc,a,mid+1,r); now->upt(); } inline void insert_val(node1 *&now,int pos,int val,node1**&p){ if(now==null1){ now=newnode1(val); insert2(now->rt,0,Maxn-1,val); return; } insert2(now->rt,0,Maxn-1,val); if(now->lc->sze+now->exi<=pos)insert_val(now->rc,pos-now->lc->sze-now->exi,val,p); else insert_val(now->lc,pos,val,p); now->upt(); if(now->sze*alpha<now->lc->sze*100||now->sze*alpha<now->rc->sze*100)p=&now; } inline void rebuild(node1 *&now){ tot=0; recyclenode1(now,a); build(now,a,1,tot); } inline void insert(int pos,int val){ node1 **p=&null1; insert_val(rt,pos,val,p); if(*p!=null1)rebuild(*p); } inline void erase_val(node1*& now,int pos,int val,node1**& p){ insert2(now->rt,0,Maxn-1,val,-1); if(now->lc->sze>=pos)erase_val(now->lc,pos,val,p); else if(now->lc->sze+now->exi==pos)now->exi=0; else erase_val(now->rc,pos-now->lc->sze-now->exi,val,p); now->upt(); if(now->sze*alpha<now->lc->sze*100||now->sze*alpha<now->rc->sze*100)p=&now; } inline void del(int pos,int val){ node1 **p=&null1; erase_val(rt,pos,val,p); if(*p!=null1)rebuild(*p); } inline int findkth(int pos){ node1 *tmp=rt; while(tmp!=null1){ if(tmp->lc->sze>=pos)tmp=tmp->lc; else if(tmp->lc->sze+tmp->exi==pos)return tmp->val; else pos-=(tmp->lc->sze+tmp->exi),tmp=tmp->rc; } } inline void find(node1 *now,int l,int r,int L,int R){ if(L<=l&&r<=R){if(now->rt!=null2)que[++tail]=now->rt;return;} if(now->lc!=null1&&l+now->lc->sze-1>=L&&(R>=l))find(now->lc,l,l+now->lc->sze-1,L,R); if(now->rc!=null1&&l+now->lc->sze+now->exi<=R&&(r>=L))find(now->rc,l+now->lc->sze+now->exi,r,L,R); if(L<=l+now->lc->sze+now->exi-1&&l+now->lc->sze+now->exi-1<=R&&now->exi)t[++tmp]=now->val; return; } inline int query(int l,int r,int k){ tmp=tail=0; find(rt,1,rt->sze,l,r); int lval=0,rval=Maxn-1,ans=0; while(lval<=rval){ int mid=(lval+rval)>>1,cnt=0; for(int i=1;i<=tail;i++) cnt+=query2(que[i],0,Maxn-1,mid); for(int i=1;i<=tmp;i++)if(t[i]<=mid)cnt++; if(cnt>=k)ans=mid,rval=mid-1; else lval=mid+1; } return ans; }}SGT;int main(){ io.init(); n=io.read(); for(int i=1;i<=n;i++)a[i]=io.read(); SGT.build(SGT.rt,a,1,n); int m=io.read(); while(m--){ static char op[2]; cin>>(op+1); if(op[1]=='Q'){ int l=io.read()^lastans,r=io.read()^lastans,k=io.read()^lastans; lastans=SGT.query(l,r,k); io.W(lastans); } else if(op[1]=='M'){ int pos=io.read()^lastans,val=io.read()^lastans; SGT.del(pos,SGT.findkth(pos)); SGT.insert(pos-1,val); } else{ int pos=io.read()^lastans,val=io.read()^lastans; SGT.insert(pos-1,val); } }}
阅读全文
0 0
- BZOJ3065: 带插入区间K小值(替罪羊树+权值线段树)
- 替罪羊树套线段树 【bzoj3065】 带插入区间k小值
- [bzoj3065]带插入区间K小值 替罪羊树套值域线段树
- BZOJ3065 带插入区间K小值
- [bzoj3065]带插入区间K小值
- bzoj3065带插入区间K小值
- BZOJ3065 带插入区间K小值
- bzoj3065: 带插入区间K小值
- 【BZOJ3065】带插入区间K小值
- BZOJ 3065 带插入区间K小值 替罪羊树套线段树
- BZOJ 3065 带插入区间K小值 替罪羊树套线段树
- bzoj 3065: 带插入区间K小值 替罪羊树套线段树
- BZOJ 3065: 带插入区间K小值 替罪羊树套权值线段树 详解
- [bzoj3065]带插入区间K小值 解题报告
- [分块 块的分裂 || 替罪羊树套线段树] BZOJ 3065 带插入区间K小值
- bzoj 3065: 带插入区间K小值 替罪羊树套主席树
- BZO3065 带插入区间K小值
- 3065: 带插入区间K小值
- angularjs速成学习个人理解_4依赖注入
- centos下svn安装,svn用户管理,svn用户目录管理(虚拟机下访问)
- 实战tcpdump看RST
- 前端安全问题初探
- STL之list容器详解
- BZOJ3065: 带插入区间K小值(替罪羊树+权值线段树)
- Exception in thread "main" java.lang.IllegalArgumentException: Wrong FS: hdfs://node1:9000/input/pia
- 机房重构
- stl之map的用法详解
- (转)金融信息服务业的国际国内竞争格局及新动向
- mysql innodb读书笔记
- http权威指南 读书笔记
- redis 读书笔记
- 关于禁止html缓存