今天才发现加上回收空间的话主席树的空间是nlognlogn→ →之前总当成和树套树一样是nlogn了【你特喵在逗我
在BZOJ上很久前过掉了,今天滚回来写ZOJ各种卡空间
ZOJ上32768K实在是……卡死了
所以,为了压缩空间,我们拆成两部分来做。
首先静态建树,直接把给定的序列离散化丢到一棵树里【就像POJ2104那样玩】,这里的空间是nlogn,如果直接用树状数组去套的话空间就是nlognlogn在ZOJ上就无限MLE了……
那么更新怎么办呢?
再造一棵树用来记录更新,这棵树要用树状数组来套,这里的空间最多是mlognlogn。
这样总的空间复杂度就是nlogn+mlognlogn,因为总的操作数m<=10000,但是n<=50000,于是空间就降下来了,在ZOJ上基本上31000K左右的空间就能AC了。
这方法玩得真脱呀……………………
ZOJ 2112
#define NN 50005
#define NM 10005
#define MM 2600010
int root[NN],rt1[NN],a[NN],b[NN+NM],n,q,node,lb,poi;
int ord[NM][4]; int bit[NN];
struct sgtree{ int l,r,s; }tree[MM];
int sta[NM],top;
int fastget()
{
char c; int ans=0; c=getchar();
while (! (c>='0' && c<='9')) c=getchar();
while (c>='0' && c<='9')
{
ans=(ans<<3)+(ans<<1)+c-'0';
c=getchar();
}
return ans;
}
int search(int x)
{
int l=1,r=b[0],mid;
while (l<=r)
{
mid=l+r>>1; if(b[mid]==x) return mid;
if(b[mid]<x) l=mid+1; else r=mid-1;
}
}
int build(int l,int r)
{
int k=++node;
tree[k].s=0;
if(l==r) return k;
int mid=l+r>>1;
if(l<=mid) tree[k].l=build(l,mid);
if(r>mid) tree[k].r=build(mid+1,r);
return k;
}
int sum(int x)
{
int ans=0;
for(;x;x-=lowbit(x)) ans+=tree[tree[bit[x]].l].s;
return ans;
}
int query(int x,int y,int xx,int yy,int l,int r,int k)
{
if(l==r) return l;
int ans=tree[tree[yy].l].s-tree[tree[xx].l].s+sum(y)-sum(x);
int mid=l+r>>1;
if(ans>=k)
{
for(int i=x;i;i-=lowbit(i)) bit[i]=tree[bit[i]].l;
for(int i=y;i;i-=lowbit(i)) bit[i]=tree[bit[i]].l;
return query(x,y,tree[xx].l,tree[yy].l,l,mid,k);
}
else
{
for(int i=x;i;i-=lowbit(i)) bit[i]=tree[bit[i]].r;
for(int i=y;i;i-=lowbit(i)) bit[i]=tree[bit[i]].r;
return query(x,y,tree[xx].r,tree[yy].r,mid+1,r,k-ans);
}
}
int update(int rt,int l,int r,int x,int d)
{
int k=++node;
tree[k]=tree[rt];
tree[k].s+=d;
if(l==r) return k;
int mid=l+r>>1;
if(x<=mid) tree[k].l=update(tree[rt].l,l,mid,x,d);
else tree[k].r=update(tree[rt].r,mid+1,r,x,d);
return k;
}
int main()
{
freopen("1.in","r",stdin);
int tt=fastget();
while(tt--)
{
top=node=0;
lb=n=fastget(); q=fastget();
for(int i=1;i<=n;i++) b[i]=a[i]=fastget();
for(int i=1;i<=q;i++)
{
char s[3]; scanf("%s",s);
if(s[0]=='Q'){ ord[i][0]=1; ord[i][1]=fastget(); ord[i][2]=fastget(); ord[i][3]=fastget(); }
else{ ord[i][0]=2; ord[i][1]=fastget(); b[++lb]=ord[i][2]=fastget(); }
}
sort(b+1,b+1+lb); b[0]=1;
for(int i=2;i<=lb;i++) if(b[i]!=b[b[0]]) b[++b[0]]=b[i];
for(int i=1;i<=n;i++) a[i]=search(a[i]);
root[0]=build(1,b[0]); poi=node;
for(int i=1;i<=n;i++) rt1[i]=root[0];
for(int i=1;i<=n;i++)
root[i]=update(root[i-1],1,b[0],a[i],1);
for(int _=1;_<=q;_++)
{
if(ord[_][0]==1)
{
int u=ord[_][1],v=ord[_][2],w=ord[_][3];
for(int i=u-1;i;i-=lowbit(i)) bit[i]=rt1[i];
for(int i=v;i;i-=lowbit(i)) bit[i]=rt1[i];
printf("%d\n",b[query(u-1,v,root[u-1],root[v],1,b[0],w)]);
}
else
{
int u=ord[_][1],w=ord[_][2];
for(int i=u;i<=n;i+=lowbit(i)) rt1[i]=update(rt1[i],1,b[0],a[u],-1);
a[u]=search(w);
for(int i=u;i<=n;i+=lowbit(i)) rt1[i]=update(rt1[i],1,b[0],a[u],1);
}
}
}
return 0;
}
#define NN 10005
#define NM 10005
#define MM 2500010
int root[NN],a[NN],b[NN+NM],n,q,node,lb,poi;
int ord[NM][4]; int bit[NN];
struct sgtree{ int l,r,s; }tree[MM];
int sta[NM],top;
int fastget()
{
char c; int ans=0; c=getchar();
while (! (c>='0' && c<='9')) c=getchar();
while (c>='0' && c<='9')
{
ans=(ans<<3)+(ans<<1)+c-'0';
c=getchar();
}
return ans;
}
int search(int x)
{
int l=1,r=b[0],mid;
while (l<=r)
{
mid=l+r>>1; if(b[mid]==x) return mid;
if(b[mid]<x) l=mid+1; else r=mid-1;
}
}
int build(int l,int r)
{
int k=++node;
tree[k].s=0;
if(l==r)
{
tree[k].l=tree[k].r=0;
return k;
}
int mid=l+r>>1;
if(l<=mid) tree[k].l=build(l,mid);
if(r>mid) tree[k].r=build(mid+1,r);
return k;
}
int sum(int x)
{
int ans=0;
for(;x;x-=lowbit(x)) ans+=tree[tree[bit[x]].l].s;
return ans;
}
int query(int x,int y,int l,int r,int k)
{
if(l==r) return l;
int ans=sum(y)-sum(x);
int mid=l+r>>1;
if(ans>=k)
{
for(int i=x;i;i-=lowbit(i)) bit[i]=tree[bit[i]].l;
for(int i=y;i;i-=lowbit(i)) bit[i]=tree[bit[i]].l;
return query(x,y,l,mid,k);
}
else
{
for(int i=x;i;i-=lowbit(i)) bit[i]=tree[bit[i]].r;
for(int i=y;i;i-=lowbit(i)) bit[i]=tree[bit[i]].r;
return query(x,y,mid+1,r,k-ans);
}
}
int update(int rt,int l,int r,int x,int d)
{
int k;
if(top) k=sta[--top];
else k=++node;
tree[k]=tree[rt];
tree[k].s+=d;
if(l==r)
{
tree[k].l=tree[k].r=0;
return k;
}
int mid=l+r>>1;
if(x<=mid)
{
if(tree[k].l>poi) sta[top++]=tree[k].l;
tree[k].l=update(tree[rt].l,l,mid,x,d);
}
else
{
if(tree[k].r>poi) sta[top++]=tree[k].r;
tree[k].r=update(tree[rt].r,mid+1,r,x,d);
}
return k;
}
int main()
{
top=node=0;
lb=n=fastget(); q=fastget();
for(int i=1;i<=n;i++) b[i]=a[i]=fastget();
for(int i=1;i<=q;i++)
{
char s[3]; scanf("%s",s);
if(s[0]=='Q'){ ord[i][0]=1; ord[i][1]=fastget(); ord[i][2]=fastget(); ord[i][3]=fastget(); }
else{ ord[i][0]=2; ord[i][1]=fastget(); b[++lb]=ord[i][2]=fastget(); }
}
sort(b+1,b+1+lb); b[0]=1;
for(int i=2;i<=lb;i++) if(b[i]!=b[b[0]]) b[++b[0]]=b[i];
for(int i=1;i<=n;i++) a[i]=search(a[i]);
root[0]=build(1,b[0]); poi=node;
for(int i=1;i<=n;i++) root[i]=root[0];
for(int i=1;i<=n;i++)
for(int x=i;x<=n;x+=lowbit(x))
root[x]=update(root[x],1,b[0],a[i],1);
for(int _=1;_<=q;_++)
{
if(ord[_][0]==1)
{
int u=ord[_][1],v=ord[_][2],w=ord[_][3];
for(int i=u-1;i;i-=lowbit(i)) bit[i]=root[i];
for(int i=v;i;i-=lowbit(i)) bit[i]=root[i];
printf("%d\n",b[query(u-1,v,1,b[0],w)]);
}
else
{
int u=ord[_][1],w=ord[_][2];
for(int i=u;i<=n;i+=lowbit(i)) root[i]=update(root[i],1,b[0],a[u],-1);
a[u]=search(w);
for(int i=u;i<=n;i+=lowbit(i)) root[i]=update(root[i],1,b[0],a[u],1);
}
}
return 0;
}