题目描述
一道垃圾的区间带修第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=1;i<=m;i++)
{
if(q[i].kd)
{
add(q[i].l,-1);
a[q[i].l]=q[i].val;
add(q[i].l,1);
}
else
{
printf("%d\n",get(q[i].l,q[i].r,q[i].val));
}
}
// printf("%d\n",cnt);
}
替罪羊树
#include<bits/stdc++.h>
#define alpha 0.75
using namespace std;
struct tree
{
int l,r;
}tr[800040];
struct que
{
int kd,ll,rr,vv;
}q[200020];
struct point
{
int son[2],real,sz,val,vis;
}t[3000010];
int rt[800040],a[200020];
int sta[3000010],tmp[200020],top,cnt;
int tmp2[800020],tot;
int n,m,ttt;
char op[2];
inline int read()
{
int f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
void init()
{
for(int i=1;i<=3000000;i++) sta[++top]=i;
sort(tmp2+1,tmp2+tot+1);
tot=unique(tmp2+1,tmp2+tot+1)-tmp2-1;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(tmp2+1,tmp2+tot+1,a[i])-tmp2;
}
for(int i=1;i<=m;i++)
{
if(q[i].kd==2) q[i].vv=lower_bound(tmp2+1,tmp2+tot+1,q[i].vv)-tmp2;
}
}
#define lson t[now].son[0]
#define rson t[now].son[1]
inline int bad(int now)
{
return (double) t[now].sz*alpha<=(double) max(t[lson].sz,t[rson].sz);
}
void push_up(int now)
{
t[now].real=t[lson].real+t[rson].real+1;
t[now].sz=t[lson].sz+t[rson].sz+1;
}
void build(int now)
{
lson=rson=0;
t[now].sz=t[now].real=1;
}
void la(int &now,int l,int r)
{
int mid=(l+r)>>1;
now=tmp[mid];
if(l==r)
{
build(now);
return ;
}
if(l<mid) la(lson,l,mid-1);
else lson=0;
la(rson,mid+1,r);
push_up(now);
}
void pia(int now)
{
if(!now) return ;
pia(lson);
if(t[now].vis) tmp[++cnt]=now;
else sta[++top]=now;
pia(rson);
}
void rebuild(int &now)
{
cnt=0;
pia(now);
if(cnt>0) la(now,1,cnt);
else now=0;
}
void insert(int &now,int val)
{
if(!now)
{
now=sta[top--];
t[now].val=val;
t[now].vis=1;
build(now);
return;
}
t[now].real++;
t[now].sz++;
if(t[now].val>=val) insert(lson,val);
else insert(rson,val);
if(bad(now)) rebuild(now);
}
int get_rk(int now,int val)
{
int tot=1;
while(now)
{
if(t[now].val>=val) now=lson;
else tot+=t[now].vis+t[lson].real,now=rson;
}
return tot;
}
int get_val(int now,int rk)
{
while(now)
{
if(rk==t[now].vis+t[lson].real&&t[now].vis) return t[now].val;
if(t[now].vis+t[lson].real>=rk) now=lson;
else rk-=t[now].vis+t[lson].real;
}
}
void del_rk(int &now,int rk)
{
if(t[now].vis&&t[now].vis+t[lson].real==rk)
{
t[now].real--;
t[now].vis=0;
return ;
}
t[now].real--;
if(t[now].vis+t[lson].real>=rk) del_rk(lson,rk);
else del_rk(rson,rk-t[now].vis-t[lson].real);
}
void del_val(int &now,int val)
{
int rk=get_rk(now,val);
del_rk(now,rk);
if((double)t[now].sz*alpha>=t[now].real) rebuild(now);
}
void debug(int now)
{
if(lson) debug(lson);
if(t[now].vis) printf("%d ",t[now].val);
if(rson) debug(rson);
}
#undef lson
#undef rson
#define lson root<<1
#define rson root<<1|1
void build(int root,int l,int r)
{
rt[root]=sta[top--];
tr[root].l=l;
tr[root].r=r;
if(l==r)
{
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
}
void del(int root,int pos,int val)
{
del_val(rt[root],val);
if(tr[root].l==tr[root].r)
{
return;
}
int mid=(tr[root].l+tr[root].r)>>1;
if(pos<=mid) del(lson,pos,val);
else del(rson,pos,val);
}
void update(int root,int pos,int val)
{
insert(rt[root],val);
if(tr[root].l==tr[root].r)
{
return;
}
int mid=(tr[root].l+tr[root].r)>>1;
if(pos<=mid) update(lson,pos,val);
else update(rson,pos,val);
}
int query(int root,int ll,int rr,int l,int r,int kk)
{
if(ll==rr)
{
return tmp2[ll];
}
int sz=get_rk(rt[lson],r+1)-get_rk(rt[lson],l);
int mid=(ll+rr)>>1;
if(sz>=kk)
{
return query(lson,ll,mid,l,r,kk);
}
else
{
return query(rson,mid+1,rr,l,r,kk-sz);
}
}
#undef lson
#undef rson
int main()
{
freopen("1.in","r",stdin);
freopen("1.ans","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
tmp2[++tot]=a[i];
}
for(int i=1;i<=m;i++)
{
scanf("%s",op);
if(op[0]=='Q')
{
q[i].ll=read();
q[i].rr=read();
q[i].vv=read();
q[i].kd=1;
}
else
{
if(op[0]=='C')
{
q[i].ll=read();
q[i].vv=read();
q[i].kd=2;
tmp2[++tot]=q[i].vv;
}
}
}
init();
build(1,1,tot);
for(int i=1;i<=n;i++)
{
update(1,a[i],i);
}
for(int i=1;i<=m;i++)
{
if(q[i].kd==1)
{
printf("%d\n",query(1,1,tot,q[i].ll,q[i].rr,q[i].vv));
}
else
{
del(1,a[q[i].ll],q[i].ll);
update(1,q[i].vv,q[i].ll);
a[q[i].ll]=q[i].vv;
}
}
}
权值线段树
#include<bits/stdc++.h>
#define lson1 root<<1
#define rson1 root<<1|1
#define lson2 tr2[now].l
#define rson2 tr2[now].r
using namespace std;
int n,m,b[800020],a[800020],tot,rt[800020],tmp,cnt;
struct op
{
int kd,l,r,val;
}p[800010];
struct tree1
{
int l,r;
}tr1[800040];
struct tree2
{
int l,r,sum;
}tr2[30000050];
inline int read()
{
int f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
void init()
{
sort(b+1,b+cnt+1);
tot=unique(b+1,b+cnt+1)-b-1;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
}
for(int i=1;i<=m;i++)
{
if(p[i].kd==2)
{
p[i].val=lower_bound(b+1,b+tot+1,p[i].val)-b;
}
}
}
//segment_tree2
void update2(int &now,int l,int r,int pos,int val)
{
if(!now) now=++tmp;
if(l==r)
{
tr2[now].sum+=val;
return ;
}
register int mid=(l+r)>>1;
if(pos<=mid)
{
update2(lson2,l,mid,pos,val);
}
else
{
update2(rson2,mid+1,r,pos,val);
}
tr2[now].sum=tr2[lson2].sum+tr2[rson2].sum;
}
int query2(int now,int l,int r,int ll,int rr)
{
if(ll<=l&&r<=rr) return tr2[now].sum;
register int mid=(l+r)>>1;
if(rr<=mid)
{
return query2(lson2,l,mid,ll,rr);
}
else
{
if(ll>mid)
{
return query2(rson2,mid+1,r,ll,rr);
}
else
{
return query2(lson2,l,mid,ll,mid)+query2(rson2,mid+1,r,mid+1,rr);
}
}
}
//end
//segment_tree1
void build(int root,int l,int r)
{
if(l==r)
{
tr1[root].l=l;
tr1[root].r=r;
return ;
}
rt[root]=++tmp;
tr1[root].l=l;
tr1[root].r=r;
int mid=(l+r)>>1;
build(lson1,l,mid);
build(rson1,mid+1,r);
}
void insert(int root,int pos,int val)
{
if(tr1[root].l==tr1[root].r)
{
update2(rt[root],1,n,val,1);
return ;
}
update2(rt[root],1,n,val,1);
register int mid=(tr1[root].l+tr1[root].r)>>1;
if(pos<=mid)
{
insert(lson1,pos,val);
}
else
{
insert(rson1,pos,val);
}
}
void update(int root,int pos,int val)
{
if(tr1[root].l==tr1[root].r)
{
update2(rt[root],1,n,val,1);
return ;
}
update2(rt[root],1,n,val,1);
register int mid=(tr1[root].l+tr1[root].r)>>1;
if(pos<=mid)
{
update(lson1,pos,val);
}
else
{
update(rson1,pos,val);
}
}
void del(int root,int pos,int val)
{
if(tr1[root].l==tr1[root].r)
{
update2(rt[root],1,n,val,-1);
return ;
}
update2(rt[root],1,n,val,-1);
int mid=(tr1[root].l+tr1[root].r)>>1;
if(pos<=mid)
{
del(lson1,pos,val);
}
else
{
del(rson1,pos,val);
}
}
int query(int root,int l,int r,int gg)
{
if(tr1[root].l==tr1[root].r)
{
return b[tr1[root].l];
}
int sz=query2(rt[lson1],1,n,l,r);
if(sz>=gg)
{
return query(lson1,l,r,gg);
}
else
{
return query(rson1,l,r,gg-sz);
}
}
//end
int main()
{
scanf("%d%d",&n,&m);
cnt=n;
for(int i=1;i<=n;i++)
{
a[i]=read();
b[i]=a[i];
}
char kd[10];
for(int i=1;i<=m;i++)
{
scanf("%s",kd);
if(kd[0]=='Q')
{
p[i].kd=1;
p[i].l=read();
p[i].r=read();
p[i].val=read();
}
else
{
p[i].kd=2;
p[i].l=read();
p[i].val=read();
b[++cnt]=p[i].val;
}
}
init();
build(1,1,tot);
// printf("%d\n",tot);
for(int i=1;i<=n;i++)
{
// printf("%d %d\n",i,a[i]);
insert(1,a[i],i);
}
int mag=0;
for(int i=1;i<=m;i++)
{
if(p[i].kd==1)
{
printf("%d\n",query(1,p[i].l,p[i].r,p[i].val));
}
else
{
del(1,a[p[i].l],p[i].l);
update(1,p[i].val,p[i].l);
a[p[i].l]=p[i].val;
}
}
}