# 「模板」 树套树

<题目链接>

#include <algorithm>
#include <climits>
#include <cstdio>
using std::max;
using std::min;
const int MAXN=50010;
int n,m;
class SegmentTree
{
private:
int a[MAXN];
class SBT
{
private:
struct Node
{
int v,size;
Node *c[2];
Node(int v):v(v),size(1)
{
c[0]=c[1]=nullptr;
}
~Node(void)
{
if(c[0]!=nullptr)
delete c[0];
if(c[1]!=nullptr)
delete c[1];
}
int Size(bool p)
{
return c[p]!=nullptr ? c[p]->size : 0;
}
int SubSize(bool p,bool q)
{
return c[p]!=nullptr ? c[p]->Size(q) : 0;
}
void Update(void)
{
size=Size(0)+Size(1)+1;
}
}*rt;
void Rotate(Node* &i,bool p)
{
Node *t=i->c[!p];
i->c[!p]=t->c[p];
t->c[p]=i;
i->Update();
(i=t)->Update();
}
void Maintain(Node* &i,bool p)
{
int t=i->Size(!p);
if(t<i->SubSize(p,p))
Rotate(i,!p);
else if(t<i->SubSize(p,!p))
{
Rotate(i->c[p],p);
Rotate(i,!p);
}
else
return;
Maintain(i->c[0],0);
Maintain(i->c[1],1);
Maintain(i,0);
Maintain(i,1);
}
void Insert(Node* &i,int x)
{
if(i==nullptr)
{
i=new Node(x);
return;
}
bool p=x>i->v;
++i->size;
Insert(i->c[p],x);
Maintain(i,p);
}
void Delete(Node* &i,int x)
{
if(i==nullptr)
return;
if(x==i->v)
if(i->c[1]==nullptr)
{
Node *t=i;
i=i->c[0];
t->c[0]=t->c[1]=nullptr;
delete t;
return;
}
else
{
Node *t=i->c[1];
while(t->c[0]!=nullptr)
t=t->c[0];
i->v=t->v;
Delete(i->c[1],t->v);
}
else
Delete(i->c[x>i->v],x);
i->Update();
}
public:
SBT(int* a,int l,int r):rt(nullptr)
{
for(int i=l;i<=r;++i)
Insert(a[i]);
}
~SBT(void)
{
delete rt;
}
void Insert(int x)
{
Insert(rt,x);
}
void Delete(int x)
{
Delete(rt,x);
}
int Rank(int x)
{
int ans=1;
Node *i=rt;
while(i!=nullptr)
if(x>i->v)
{
ans+=i->Size(0)+1;
i=i->c[1];
}
else
i=i->c[0];
return ans-1;
}
int Prev(int x)
{
int ans=-INT_MAX;
Node *i=rt;
while(i!=nullptr)
if(x>i->v)
{
ans=max(ans,i->v);
i=i->c[1];
}
else
i=i->c[0];
return ans;
}
int Next(int x)
{
int ans=INT_MAX;
Node *i=rt;
while(i!=nullptr)
if(x<i->v)
{
ans=min(ans,i->v);
i=i->c[0];
}
else
i=i->c[1];
return ans;
}
};
struct Node
{
SBT *T;
int l,r;
Node *c[2];
Node(SBT* T,int l,int r):T(T),l(l),r(r)
{
c[0]=c[1]=nullptr;
}
~Node(void)
{
delete T;
if(c[0]!=nullptr)
delete c[0];
if(c[1]!=nullptr)
delete c[1];
}
}*rt;
void Build(Node* &i,int l,int r)
{
i=new Node(new SBT(a,l,r),l,r);
if(l^r)
{
int mid=l+r>>1;
Build(i->c[0],l,mid);
Build(i->c[1],mid+1,r);
}
}
int Rank(Node* i,int l,int r,int k)
{
if(l==i->l && r==i->r)
return i->T->Rank(k);
int mid=i->l+i->r>>1;
if(r<=mid)
return Rank(i->c[0],l,r,k);
else if(l>mid)
return Rank(i->c[1],l,r,k);
else
return Rank(i->c[0],l,mid,k)+Rank(i->c[1],mid+1,r,k);
}
void Modify(Node* i,int pos,int k)
{
i->T->Delete(a[pos]);
i->T->Insert(k);
if(pos==i->l && pos==i->r)
return;
int mid=i->l+i->r>>1;
if(pos>mid)
Modify(i->c[1],pos,k);
else
Modify(i->c[0],pos,k);
}
int Prev(Node* i,int l,int r,int k)
{
if(l==i->l && r==i->r)
return i->T->Prev(k);
int mid=i->l+i->r>>1;
if(r<=mid)
return Prev(i->c[0],l,r,k);
else if(l>mid)
return Prev(i->c[1],l,r,k);
else
return max(Prev(i->c[0],l,mid,k),Prev(i->c[1],mid+1,r,k));
}
int Next(Node* i,int l,int r,int k)
{
if(l==i->l && r==i->r)
return i->T->Next(k);
int mid=i->l+i->r>>1;
if(r<=mid)
return Next(i->c[0],l,r,k);
else if(l>mid)
return Next(i->c[1],l,r,k);
else
return min(Next(i->c[0],l,mid,k),Next(i->c[1],mid+1,r,k));
}
public:
SegmentTree(int n):rt(nullptr)
{
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
Build(rt,1,n);
}
~SegmentTree(void)
{
delete rt;
}
void Rank(void)
{
int l,r,k;
scanf("%d %d %d",&l,&r,&k);
printf("%d\n",Rank(rt,l,r,k)+1);
}
void Find(void)
{
int l,r,k,left=0,right=int(1e8),mid;
scanf("%d %d %d",&l,&r,&k);
while(left<right)
{
int mid=left+right>>1;
if(k>Rank(rt,l,r,mid))
left=mid+1;
else
right=mid;
}
printf("%d\n",left-1);
}
void Modify(void)
{
int pos,k;
scanf("%d %d",&pos,&k);
Modify(rt,pos,k);
a[pos]=k;
}
void Prev(void)
{
int l,r,k;
scanf("%d %d %d",&l,&r,&k);
printf("%d\n",Prev(rt,l,r,k));
}
void Next(void)
{
int l,r,k;
scanf("%d %d %d",&l,&r,&k);
printf("%d\n",Next(rt,l,r,k));
}
};
int main(int argc,char** argv)
{
scanf("%d %d",&n,&m);
static SegmentTree *T=new SegmentTree(n);
for(int i=1,opt;i<=m;++i)
{
scanf("%d",&opt);
switch(opt)
{
case 1:
T->Rank();
break;
case 2:
T->Find();
break;
case 3:
T->Modify();
break;
case 4:
T->Prev();
break;
case 5:
T->Next();
break;
}
}
delete T;
return 0;
}

posted @ 2018-05-26 11:59  Capella  阅读(178)  评论(2编辑  收藏  举报