题目描述
一道垃圾的区间带修第k大写了一天
线段树套splay TLE
优化成两个log TLE
套替罪羊树 TLE
套权值线段树 TLE
算了吧,就当模板带修主席树吧
带修主席树这玩意真暴力
就用个树状数组把一堆线段树套起来
然后求的时候把每个树状数组里的点都暴力提取出来,直接暴力对每个点对应的数统计答案,树上二分
模板题也没什么好说的,垃圾……
代码如下:
#include<bits/stdc++.h>
#define lson tr[now].l
#define rson tr[now].r
using namespace std;
inline int lowbit(int x)
{
return x&(-x);
}
struct tree
{
int l,r,sum;
}tr[40000030];
int cnt,rt[400020];
int tota,totb,tmpa[400020],tmpb[400020];
int a[400020],tot,b[400020];
int n,m;
struct que
{
int kd,l,r,val;
}q[400020];
void insert(int &now,int pre,int l,int r,int pos,int val)
{
now=++cnt;
tr[now]=tr[pre];
tr[now].sum+=val;
if(l==r)
{
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) insert(lson,tr[pre].l,l,mid,pos,val);
else insert(rson,tr[pre].r,mid+1,r,pos,val);
}
int query(int l,int r,int kk)
{
if(l==r)
{
return b[l];
}
int mid=(l+r)>>1;
int sz=0;
for(int i=1;i<=tota;i++) sz+=tr[tr[tmpa[i]].l].sum;
for(int i=1;i<=totb;i++) sz-=tr[tr[tmpb[i]].l].sum;
if(kk<=sz)
{
for(int i=1;i<=tota;i++) tmpa[i]=tr[tmpa[i]].l;
for(int i=1;i<=totb;i++) tmpb[i]=tr[tmpb[i]].l;
return query(l,mid,kk);
}
else
{
for(int i=1;i<=tota;i++) tmpa[i]=tr[tmpa[i]].r;
for(int i=1;i<=totb;i++) tmpb[i]=tr[tmpb[i]].r;
return query(mid+1,r,kk-sz);
}
}
void add(int pos,int val)
{
int vp=lower_bound(b+1,b+tot+1,a[pos])-b;
for(int i=pos;i<=n;i+=lowbit(i))
{
insert(rt[i],rt[i],1,tot,vp,val);
}
}
int get(int l,int r,int kk)
{
tota=0,totb=0;
for(int i=r;i>0;i-=lowbit(i)) tmpa[++tota]=rt[i];
for(int i=l-1;i>0;i-=lowbit(i)) tmpb[++totb]=rt[i];
return query(1,tot,kk);
}
char s[10];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[++tot]=a[i];
for(int i=1;i<=m;i++)
{
scanf("%s",s);
if(s[0]=='Q')
{
q[i].kd=0;
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].val);
}
else
{
q[i].kd=1;
scanf("%d%d",&q[i].l,&q[i].val);
b[++tot]=q[i].val;
}
}
sort(b+1,b+tot+1);
tot=unique(b+1,b+tot+1)-b-1;
for(int i=1;i<=n;i++) add(i,1);
for(int i