您的位置:首页 > 其它

1901: Zju2112 Dynamic Rankings 【带修改的区间第k小数】

2014-10-14 17:12 465 查看

Description

给定一个含有n个数的序列a[1],a[2],a[3]……a
,程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。
第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a
,这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。

Input

对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

Output

Sample Input

5 3

3 2 1 4 7

Q 1 4 3

C 2 6

Q 2 5 3

Sample Output

3

6

HINT

20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。

带修改的区间第k小数查询
首先我们先不考虑修改操作。那么,写个主席树就好了。
可是现在有修改操作!如果修改了x节点那么x到n的树都需要进行修改。
当然我们可以一棵棵树来修改。可是那样就超时了。
我们这和以前做的树状数组单点修改区间求和类似。所以也许可以用树状数组来维护。
每个树状数组的节点就是一棵主席树,然后修改的时候就和以前做单点修改一样,把对应的树状数组节点的值都改变即可。
如果询问是s t k,那么我们只需要用1到t的减去1到s的然后和没修改操作的一样求区间第k小就可以了。
哦对了因为主席树是离线的。。所以我们需要先把所有出现的数都离散化。

这题是个坑。。嗯。我竟然写了230行。。看着别人100行左右的。我都不好意思贴出来了
以下是代码。。我觉得我写的应该蛮清楚的。。除了离散化那段
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree
{
int l,r;
int ll,rr;
int s;
}tr[3000001];
int tot;
int ss;
int pl[100001];
int a[100001];
int n,px;
inline void build(int l,int r)
{
int p=tot;
tr[p].l=l;
tr[p].r=r;
if(l!=r)
{
int mid=(l+r)/2;
tot++;
tr[p].ll=tot;
tot++;
tr[p].ll=tot;
build(l,mid);
tot++;
tr[p].rr=tot;
build(mid+1,r);
tr[p].s=tr[tr[p].ll].s+tr[tr[p].rr].s;
}
}
inline int inc(int p,int l,int r,int x)
{
if(p==0)
return 0;
if(tr[p].l==l&&tr[p].r==r)
{
tot++;
tr[tot].l=l;
tr[tot].r=r;
tr[tot].s=tr[p].s+x;
return tot;
}
else
{
int mid=(tr[p].l+tr[p].r)/2;
tot++;
int pp=tot;
tr[pp].l=tr[p].l;
tr[pp].r=tr[p].r;
if(l<=mid)
tr[pp].ll=inc(tr[p].ll,l,r,x);
else
tr[pp].ll=tr[p].ll;
if(r>mid)
tr[pp].rr=inc(tr[p].rr,l,r,x);
else
tr[pp].rr=tr[p].rr;
tr[pp].s=tr[tr[pp].ll].s+tr[tr[pp].rr].s;
return pp;
}
}
int N,M;
int L[300],R[300];
inline int ask(int l,int r,int k)
{
if(l==r)
return l;
else
{
int tmp1=0,tmp2=0;
int i;
for(i=1;i<=N;i++)
tmp1+=tr[tr[L[i]].ll].s;
for(i=1;i<=M;i++)
tmp2+=tr[tr[R[i]].ll].s;
int tmp=tmp2-tmp1;
int mid=(l+r)/2;
if(k<=tmp)
{
for(i=1;i<=N;i++)
L[i]=tr[L[i]].ll;
for(i=1;i<=M;i++)
R[i]=tr[R[i]].ll;
return ask(l,mid,k);
}
else
{
for(i=1;i<=N;i++)
L[i]=tr[L[i]].rr;
for(i=1;i<=M;i++)
R[i]=tr[R[i]].rr;
return ask(mid+1,r,k-tmp);
}
}
}
inline int lowbit(int x)
{
return x&(-x);
}
inline void bit_inc(int l,int tt,int x)
{
int i;
int tx;
for(i=l;i<=n;i+=lowbit(i))
{
tx=pl[i];
pl[i]=tot+1;
if(tx==0)
tx=1;
inc(tx,tt,tt,x);
}
}
inline int bit_ask(int l,int r,int k)
{
int i;
N=0;
M=0;
for(i=l;i>=1;i-=lowbit(i))
{
N++;
L
=pl[i];
}
for(i=r;i>=1;i-=lowbit(i))
{
M++;
R[M]=pl[i];
}
return ask(1,px,k);
}

struct number
{
int t,x;
}b[100001];
int fx[100001];
int pp[100001];
inline bool cmp1(number x,number y)
{
if(x.x<y.x)
return true;
return false;
}
inline bool cmp2(number x,number y)
{
if(x.t<y.t)
return true;
return false;
}
int as[100001][4];
int main()
{
int m;
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i].x=a[i];
b[i].t=i;
}
string xx;
int pxx=n;
int s,t;
for(i=1;i<=m;i++)
{
cin>>xx;
scanf("%d%d",&s,&t);//区间第x小的数
if(xx=="C")
{
as[i][0]=0;
as[i][1]=s;
as[i][2]=t;
pxx++;
b[pxx].x=t;
b[pxx].t=pxx;
}
else
{
scanf("%d",&as[i][3]);
as[i][0]=1;
as[i][1]=s;
as[i][2]=t;
}
}
sort(b+1,b+1+pxx,cmp1);
px++;
fx[px]=b[1].x;
pp[b[1].t]=px;
for(i=2;i<=pxx;i++)
{
if(b[i].x!=b[i-1].x)
{
px++;
fx[px]=b[i].x;
pp[b[i].t]=px;
}
else
pp[b[i].t]=px;
}
sort(b+1,b+1+pxx,cmp2);
tot++;
pl[0]=tot;
build(1,px);
for(i=1;i<=n;i++)
bit_inc(i,pp[i],1);
int dq=0;
for(i=1;i<=m;i++)
{
if(as[i][0]==0)
{
bit_inc(as[i][1],pp[as[i][1]],-1);
dq++;
a[as[i][1]]=as[i][2];
pp[as[i][1]]=pp[b[dq+n].t];
bit_inc(as[i][1],pp[as[i][1]],1);
}
else
printf("%d\n",fx[bit_ask(as[i][1]-1,as[i][2],as[i][3])]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: