树状数组套主席树做法
整体二分也是很优秀的,具体可以参考2013年许昊然的论文。
首先本题是可以离线做的,考虑主席树的做法,每次在一个区间中二分一个值
mid
,看
<=mid
<script type="math/tex" id="MathJax-Element-1143"><=mid</script>的数是否为
k
个,如果超过
然后整体二分又是什么呢?我们还是先二分一个值
mid
,然后看在每一个区间中,
<=mid
<script type="math/tex" id="MathJax-Element-1149"><=mid</script>的值是否为
k
个,如果超过
实测比树套树快,而且比较好写。
写完去装逼的时候yzy神犇说树套树多么好写啊,又被神犇嘲讽了。
#include<iostream>
#include<cstdio>
#define N 20005
#define inf 1000000000
#define lowbit(i) (i&(-i))
using namespace std;
int n,m,cnt,dfn;
int tree[N],a[N],ans[N],tmp[N<<1];
struct node {int x,y,k,id,cur,type;} q[N<<1],q1[N<<1],q2[N<<1];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline void add(int x,int val)
{
for (int i=x;i<=n;i+=lowbit(i)) tree[i]+=val;
}
inline int query(int x)
{
int tmp=0;
for (int i=x;i;i-=lowbit(i)) tmp+=tree[i];
return tmp;
}
void solve(int t,int w,int l,int r)
{
if (t>w) return;
if (l==r)
{
for (int i=t;i<=w;i++)
if (q[i].type==3) ans[q[i].id]=l;
return;
}
int mid=l+r>>1;
for (int i=t;i<=w;i++)
if (q[i].type==1&&q[i].y<=mid) add(q[i].x,1);
else if (q[i].type==2&&q[i].y<=mid) add(q[i].x,-1);
else if (q[i].type==3) tmp[i]=query(q[i].y)-query(q[i].x-1);
for (int i=t;i<=w;i++)
if (q[i].type==1&&q[i].y<=mid) add(q[i].x,-1);
else if (q[i].type==2&&q[i].y<=mid) add(q[i].x,1);
int p1=0,p2=0;
for (int i=t;i<=w;i++)
if (q[i].type==3)
{
if (tmp[i]+q[i].cur>=q[i].k) q1[++p1]=q[i];
else q[i].cur+=tmp[i],q2[++p2]=q[i];
}
else
{
if (q[i].y<=mid) q1[++p1]=q[i]; else q2[++p2]=q[i];
}
for (int i=1;i<=p1;i++) q[t+i-1]=q1[i];
for (int i=1;i<=p2;i++) q[t+p1+i-1]=q2[i];
solve(t,t+p1-1,l,mid); solve(t+p1,w,mid+1,r);
}
int main()
{
n=read(); m=read();
for (int i=1;i<=n;i++)
a[i]=read(),q[++cnt].x=i,q[cnt].y=a[i],q[cnt].type=1;
for (int i=1;i<=m;i++)
{
char opt[5];
scanf("%s",opt);
if (opt[0]=='Q')
q[++cnt].x=read(),q[cnt].y=read(),q[cnt].k=read(),q[cnt].type=3,q[cnt].id=++dfn;
else
{
int x=read(),y=read();
q[++cnt].x=x; q[cnt].y=a[x]; q[cnt].type=2;
q[++cnt].x=x; q[cnt].y=y; q[cnt].type=1;
a[x]=y;
}
}
solve(1,cnt,0,inf);
for (int i=1;i<=dfn;i++) printf("%d\n",ans[i]);
return 0;
}