#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
inline int min(int a,int b)
{return (a<b?a:b);}
inline int max(int a,int b)
{return (a>b?a:b);}
inline int abs(int a)
{return (a<0?-a:a);}
char c;
bool flag;
inline void read(int &a)
{
a=0;flag=false;
do c=getchar();while(c!='-'&&(c<'0'||c>'9'));
if(c=='-')c=getchar(),flag=true;
while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
if(flag)a=-a;
}
inline void print(int a)
{
if(a<0)putchar('-'),a=-a;
if(a<10){putchar('0'+a),putchar('\n');return;}
long long base=1;
while(base<=a)
base=(base<<3)+(base<<1);
base/=10;
while(base)putchar('0'+a/base),a%=base,base/=10;
putchar('\n');
}
struct Node
{
Node *f,*lc,*rc;
int data,rank,size;
inline bool l(){return this->f->lc==this;}
};
Node *sta=new Node[1000001];
int cc;
int max_Con=1000000;
Node *stack[1000001];
inline Node* Node_Stackpop()
{
return stack[cc--];
}
inline void Node_Stackpush(Node *a)
{stack[++cc]=a;}
Node *empty;
inline void begin(){empty=new Node;empty->f=empty;empty->lc=empty->rc=empty;empty->data=empty->size=empty->rank=0;cc=max_Con;for(int i=0;i<=max_Con;i++)stack[i]=sta+i;}
inline Node *New_Node(){Node *tp=Node_Stackpop();tp->lc=tp->rc=empty;tp->size=1;tp->rank=1;return tp;}
inline void up_data(Node *a)
{a->rank=a->lc->size+1;a->size=a->lc->size+a->rc->size+1;}
inline void lc_change(Node *a)
{
if(a->f==a)
return ;
Node *newf;
if(a->f->f==a->f)
newf=a;
else if(a->f->l())
a->f->f->lc=a,newf=a->f->f;
else
a->f->f->rc=a,newf=a->f->f;
a->rc->f=a->f;
a->f->lc=a->rc;
a->rc=a->f;
a->f->f=a;
a->f=newf;
up_data(a->rc);
up_data(a);
}
inline void rc_change(Node *a)
{
if(a->f==a)
return ;
Node *newf;
if(a->f->f==a->f)
newf=a;
else if(a->f->l())
a->f->f->lc=a,newf=a->f->f;
else
a->f->f->rc=a,newf=a->f->f;
a->lc->f=a->f;
a->f->rc=a->lc;
a->lc=a->f;
a->f->f=a;
a->f=newf;
up_data(a->lc);
up_data(a);
}
inline void Change(Node *a)
{a->l()?lc_change(a):rc_change(a);}
inline void Twice_Change(Node *a)
{if(a->l()==a->f->l())Change(a->f);else Change(a);Change(a);}
inline void Spaly(Node *a)
{while(a->f->f!=a->f)Twice_Change(a);while(a->f!=a)Change(a);}
inline void insert(Node *a,Node *data)
{
if(a->data>=data->data)
if(a->lc==empty)
a->lc=data,data->f=a,Spaly(data);
else insert(a->lc,data);
else if(a->rc==empty)
a->rc=data,data->f=a,Spaly(data);
else insert(a->rc,data);
}
const
int INF=100000000;
int Find_Rank(Node *a,int data)
{
if(a->data>data)
if(a->lc==empty)
return 1;
else return Find_Rank(a->lc,data);
else if(a->data==data)
if(a->lc!=empty)
return min(a->rank,Find_Rank(a->lc,data));
else return a->rank;
else if(a->rc==empty)
return a->rank+1;
else return Find_Rank(a->rc,data)+a->rank;
}
int Pre(Node *a,int data)
{
if(a->data>=data)
if(a->lc==empty)
return -INF;
else return Pre(a->lc,data);
else if(a->rc==empty)
return a->data;
else return max(a->data,Pre(a->rc,data));
}
bool Has(Node *a,int data)
{
if(a->data==data)return true;
if(a->data>data)
if(a->lc==empty)
return false;
else return Has(a->lc,data);
else if(a->rc==empty)
return false;
else return Has(a->rc,data);
}
int Aft(Node *a,int data)
{
if(a->data>data)
if(a->lc==empty)
return a->data;
else return min(a->data,Aft(a->lc,data));
else if(a->rc==empty)
return INF;
else return Aft(a->rc,data);
}
int Find_Data(Node *a,int rank)
{
if(a->rank==rank)
return a->data;
else if(a->rank>rank)
return Find_Data(a->lc,rank);
return Find_Data(a->rc,rank-a->rank);
}
struct Segement_Node
{
Node *root;
int l,r;
}Segement_Tree[1000001];
int data[1000001];
inline void Delete(Node *a,int Sege_place)
{
Node *first;
if(a==Segement_Tree[Sege_place].root)
if(a->lc!=empty)
Segement_Tree[Sege_place].root=a->lc;
else
Segement_Tree[Sege_place].root=a->rc;
else;
while(a->lc!=empty||a->rc!=empty)
if(a->lc!=empty)
Change(a->lc);
else Change(a->rc);
(a->l()?a->f->lc:a->f->rc)=empty;
up_data(a->f);
Spaly(a->f);
Segement_Tree[Sege_place].root=a->f;
Node_Stackpush(a);
}
void era(Node *a,int data,int Sege_place)
{
if(a->data==data)
Delete(a,Sege_place);
else if(a->data<data)
era(a->rc,data,Sege_place),up_data(a);
else if(a->data>data)
era(a->lc,data,Sege_place),up_data(a);
}
void Build_Segement_Tree(int place,int l,int r)
{
Segement_Tree[place].l=l;
Segement_Tree[place].r=r;
Segement_Tree[place].root=New_Node();
Segement_Tree[place].root->f=Segement_Tree[place].root;
Segement_Tree[place].root->data=data[l];
int i;
Node *tp=Segement_Tree[place].root;
for(i=l+1;i<=r;i++)
tp=New_Node(),tp->data=data[i],insert(Segement_Tree[place].root,tp),
Segement_Tree[place].root=tp;
if(l^r)
Build_Segement_Tree(place<<1,l,(l+r)>>1),Build_Segement_Tree(place<<1|1,1+((l+r)>>1),r);
}
int Change_Segement_Tree(int place,int l,int data)
{
int del_data;
if(Segement_Tree[place].l^Segement_Tree[place].r)
{
if(Segement_Tree[place<<1].r>=l)
del_data=Change_Segement_Tree(place<<1,l,data);
else
del_data=Change_Segement_Tree(place<<1|1,l,data);
era(Segement_Tree[place].root,del_data,place);
Node *tp=New_Node();
tp->data=data;
insert(Segement_Tree[place].root,tp),
Segement_Tree[place].root=tp;
return del_data;
}
else
{
del_data=Segement_Tree[place].root->data;
Segement_Tree[place].root->data=data;
return del_data;
}
}
bool Segement_Has(int place,int l,int r,int data)
{
if(l<=Segement_Tree[place].l&&Segement_Tree[place].r<=r)
return Has(Segement_Tree[place].root,data);
int re=0;
if(Segement_Tree[place<<1].r>=l)
re=Segement_Has(place<<1,l,r,data);
if(re)return true;
if(Segement_Tree[place<<1|1].l<=r)
re=Segement_Has(place<<1|1,l,r,data);
return re;
}
int Segement_Rank(int place,int l,int r,int data)
{
if(l<=Segement_Tree[place].l&&Segement_Tree[place].r<=r)
return Find_Rank(Segement_Tree[place].root,data);
int re=0;
if(Segement_Tree[place<<1].r>=l)
re+=Segement_Rank(place<<1,l,r,data)-1;
if(Segement_Tree[place<<1|1].l<=r)
re+=Segement_Rank(place<<1|1,l,r,data)-1;
return re+1;
}
int Segement_Rank2(int place,int l,int r,int data)
{
if(l<=Segement_Tree[place].l&&Segement_Tree[place].r<=r)
return Find_Rank(Segement_Tree[place].root,data);
int re=0;
if(Segement_Tree[place<<1].r>=l)
re+=Segement_Rank2(place<<1,l,r,data)-1;
if(Segement_Tree[place<<1|1].l<=r)
re+=Segement_Rank2(place<<1|1,l,r,data)-1;
return re+1;
}
int Segement_Pre(int place,int l,int r,int data)
{
if(l<=Segement_Tree[place].l&&Segement_Tree[place].r<=r)
return Pre(Segement_Tree[place].root,data);
int re=-INF;
if(Segement_Tree[place<<1].r>=l)
re=Segement_Pre(place<<1,l,r,data);
if(Segement_Tree[place<<1|1].l<=r)
re=max(re,Segement_Pre(place<<1|1,l,r,data));
return re;
}
int Segement_Aft(int place,int l,int r,int data)
{
if(l<=Segement_Tree[place].l&&Segement_Tree[place].r<=r)
return Aft(Segement_Tree[place].root,data);
int re=INF;
if(Segement_Tree[place<<1].r>=l)
re=Segement_Aft(place<<1,l,r,data);
if(Segement_Tree[place<<1|1].l<=r)
re=min(re,Segement_Aft(place<<1|1,l,r,data));
return re;
}
inline int Divid(int k,int l,int r)
{
int data,li=k,ri=Segement_Tree[1].root->size;
int mid,cp;
while(li<(ri-1))
{
mid=(li+ri)>>1;
data=Find_Data(Segement_Tree[1].root,mid);
if(Segement_Rank2(1,l,r,data)<=k)
li=mid;
else
ri=mid-1;
}
data=Find_Data(Segement_Tree[1].root,li);
if(Segement_Has(1,l,r,data)&&Segement_Rank2(1,l,r,Find_Data(Segement_Tree[1].root,ri))!=k)
return data;
else
return Find_Data(Segement_Tree[1].root,ri);
}
int main()
{
int i,n,m,j,k,l;
read(n),read(m);
for(i=1;i<=n;i++) read(data[i]);
begin();
int data;
Build_Segement_Tree(1,1,n);
for(i=1;i<=m;i++)
{
read(j);
if(j==1)
{
read(k),read(l),read(data);
print(Segement_Rank(1,k,l,data));
}
else if(j==2)
{
read(j),read(k),read(l);
print(Divid(l,j,k));
}
else if(j==3)
{
read(j),read(k);
Change_Segement_Tree(1,j,k);
}
else if(j==4)
{
read(j),read(k),read(l);
print(Segement_Pre(1,j,k,l));
}
else if(j==5)
{
read(j),read(k),read(l);
print(Segement_Aft(1,j,k,l));
}
}
return 0;
}
人生第一道树套树。。。
反正就是线段树套平衡树。。。不过听Claris说把外层换成权值线段树然后用内部平衡树维护区间可以少一个log。。。Orz反正我是不会
一开始一直RE然后才发现是自己脑残New Node的时候没有返回tp的地址 windows上居然可以过去 误
不管怎么说 还是自己太弱了QAQ