累死了,终于过了
其实也没有什么好说的,就是内层平衡树用struct包起来,外层线段树乱搞即可
唯一要注意的是求区间第k大时要二分答案,边界不能写错,详见代码
由于我太菜了,这题调了很久,不想写题解了,给个链接
#include<bits/stdc++.h>
using namespace std;
int n,m,root,minn,maxx;
int cnt,cur,ans,MX;
int ls[1010101],rs[1010101],a[50010];
struct hh
{
int v,sz,lson,rson;
}tr[101010<<7];
struct zyf_tree
{
int root;
bool leaf(int x){return !(tr[x].lson||tr[x].rson);}
void new_tr(int &k,int x)
{
k=++cnt;
tr[k].v=x;
tr[k].sz=1;
}
void push_up(int x)
{
if (leaf(x)) return;
tr[x].v=max(tr[tr[x].lson].v,tr[tr[x].rson].v);
tr[x].sz=tr[tr[x].lson].sz+tr[tr[x].rson].sz;
}
void rotate(int k,bool dir)
{
if (!dir)
{
int r=tr[k].rson;
tr[k].rson=tr[k].lson;
tr[k].lson=tr[tr[k].rson].lson;
tr[tr[k].rson].lson=tr[tr[k].rson].rson;
tr[tr[k].rson].rson=r;
push_up(tr[k].lson);
push_up(tr[k].rson);
}
else
{
int l=tr[k].lson;
tr[k].lson=tr[k].rson;
tr[k].rson=tr[tr[k].lson].rson;
tr[tr[k].lson].rson=tr[tr[k].lson].lson;
tr[tr[k].lson].lson=l;
push_up(tr[k].lson);
push_up(tr[k].rson);
}
}
void maintain(int k)
{
if (leaf(k)) return;
if (tr[tr[k].lson].sz>=tr[tr[k].rson].sz*4) rotate(k,0);
if (tr[tr[k].rson].sz>=tr[tr[k].lson].sz*4) rotate(k,1);
}
void insert(int &k,int x)
{
if (!k)
{
new_tr(k,x);
return;
}
if (leaf(k))
{
new_tr(tr[k].lson,min(x,tr[k].v));
new_tr(tr[k].rson,max(x,tr[k].v));
push_up(k);
return;
}
int l=tr[tr[k].lson].v;
if (x>l) insert(tr[k].rson,x);
else insert(tr[k].lson,x);
maintain(k);
push_up(k);
}
void del(int &k,int fa,int x)
{
if (leaf(k))
{
if (!fa)
{
k=0;
return;
}
if (tr[k].v==x)
{
if (tr[fa].lson==k) tr[fa]=tr[tr[fa].rson];
else tr[fa]=tr[tr[fa].lson];
}
return;
}
int l=tr[tr[k].lson].v;
if (x>l) del(tr[k].rson,k,x);
else del(tr[k].lson,k,x);
maintain(k);
push_up(k);
}
int rnk(int k,int x)
{
if (leaf(k))
{
if (x>tr[k].v) return 1;
return 0;
}
int l=tr[tr[k].lson].v;
if (x>l) return rnk(tr[k].rson,x)+tr[tr[k].lson].sz;
return rnk(tr[k].lson,x);
}
int kth(int k,int rnk)
{
if (leaf(k)) return tr[k].v;
if (rnk<=tr[tr[k].lson].sz) return kth(tr[k].lson,rnk);
return kth(tr[k].rson,rnk-tr[tr[k].lson].sz);
}
int pre(int k,int x)
{
int ret=INT_MIN+1;
while (tr[k].v>=x)
{
if (leaf(k)) return ret;
if (tr[tr[k].lson].v<x)
{
ret=max(ret,tr[tr[k].lson].v);
k=tr[k].rson;
}
else k=tr[k].lson;
}
if (tr[k].v<x) ret=max(ret,tr[k].v);
return ret;
}
int scc(int k,int x)
{
int ret=INT_MAX;
while (k)
{
if (tr[k].v>x) ret=min(ret,tr[k].v);
if (tr[tr[k].lson].v>x)
{
ret=min(ret,tr[tr[k].lson].v);
k=tr[k].lson;
}
else k=tr[k].rson;
}
return ret;
}
}zyf[1010101];
void insert(int &k,int l,int r,int pos,int x)
{
if (!k) k=++cur;
zyf[k].insert(zyf[k].root,x);
if (l==r) return;
int mid=(l+r)>>1;
if (pos<=mid) insert(ls[k],l,mid,pos,x);
else insert(rs[k],mid+1,r,pos,x);
}
void modify(int k,int l,int r,int pos,int x)
{
if (!k) return;
zyf[k].del(zyf[k].root,0,a[pos]);
zyf[k].insert(zyf[k].root,x);
if (l==r) return;
int mid=(l+r)>>1;
if (pos<=mid) modify(ls[k],l,mid,pos,x);
else modify(rs[k],mid+1,r,pos,x);
}
void rnk(int k,int l,int r,int x,int y,int woc)
{
if (!k) return;
if (x<=l&&r<=y)
{
ans+=zyf[k].rnk(zyf[k].root,woc);
return;
}
int mid=(l+r)>>1;
if (x<=mid) rnk(ls[k],l,mid,x,y,woc);
if (y>mid) rnk(rs[k],mid+1,r,x,y,woc);
}
int kth(int k,int x,int y)
{
int l=INT_MIN,r=MX+1,ret=0;
while (l<r)
{
int mid=(l+r)>>1;
ans=0;
rnk(root,1,n,x,y,mid);
if (ans<k) l=mid+1,ret=mid;
else r=mid;
}
return ret;
}
void get_pre(int k,int l,int r,int x,int y,int woc)
{
if (!k) return;
if (x<=l&&r<=y)
{
ans=max(ans,zyf[k].pre(zyf[k].root,woc));
return;
}
int mid=(l+r)>>1;
if (x<=mid) get_pre(ls[k],l,mid,x,y,woc);
if (y>mid) get_pre(rs[k],mid+1,r,x,y,woc);
}
void get_scc(int k,int l,int r,int x,int y,int woc)
{
if (!k) return;
if (x<=l&&r<=y)
{
ans=min(ans,zyf[k].scc(zyf[k].root,woc));
return;
}
int mid=(l+r)>>1;
if (x<=mid) get_scc(ls[k],l,mid,x,y,woc);
if (y>mid) get_scc(rs[k],mid+1,r,x,y,woc);
}
int main()
{
int cur=0,anss;
scanf("%d %d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&a[i]),insert(root,1,n,i,a[i]),MX=max(MX,a[i]);
for (int i=1;i<=m;i++)
{
int l,r,x,opt;
scanf("%d",&opt);
if (opt==1)
{
scanf("%d %d %d",&l,&r,&x);
ans=0;
rnk(root,1,n,l,r,x);
ans++;
printf("%d\n",ans);
}
if (opt==2)
{
scanf("%d %d %d",&l,&r,&x);
anss=kth(x,l,r);
printf("%d\n",anss);
}
if (opt==3)
{
scanf("%d %d",&l,&x);
modify(root,1,n,l,x);
a[l]=x;
MX=max(MX,x);
}
if (opt==4)
{
scanf("%d %d %d",&l,&r,&x);
ans=INT_MIN+1;
get_pre(root,1,n,l,r,x);
printf("%d\n",ans);
}
if (opt==5)
{
scanf("%d %d %d",&l,&r,&x);
ans=INT_MAX;
get_scc(root,1,n,l,r,x);
printf("%d\n",ans);
}
}
}
注:内层是zyf树,想学的可以看另一篇博客