12
6
2015
0

【bzoj1901】Zju2112 Dynamic Rankings

1901: Zju2112 Dynamic Rankings

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 5687  Solved: 2361
[Submit][Status][Discuss]

Description

给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的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[n],这些数都小于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。

升级版的主席树。本道题在普通的主席树上增加了修改这个操作,然而普通的主席树是无法接受的。因此我们想办法去改变主席树,考虑到一个数字序列,维护前缀我们用的是树状数组。以此类比,我们是否可以把一棵棵树当做一个个的数,然后用树状数组去维护,显然这是可行的,因此每改变一棵树,就要操作log次,因此修改的操作就变成了log2n的,对于本题的数据范围可以说轻取,询问操作也同理,一次询问需要log2n的复杂度。因此我们用nlog2n的总复杂K.O.了本题。

代码:

 

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,tot,cnt,t1,t2;
int a[10010],p[20010],x[10010],y[10010],z[10010],root[10010],L[10010],R[10010];
struct node{int l,r,sum;}tr[5000010];
char s[10];
void change(int l,int r,int &p,int x,int val)
{
    tr[++cnt]=tr[p];p=cnt;tr[p].sum+=val;
    if (l==r) return;
    int mid=(l+r)>>1;
    if (x<=mid) change(l,mid,tr[p].l,x,val);else change(mid+1,r,tr[p].r,x,val);
}
int ask(int l,int r,int k)
{
    if (l==r) return l;
    int sum1=0,sum2=0;
    for (int i=1;i<=t1;i++)
        sum1+=tr[tr[L[i]].l].sum;
    for (int i=1;i<=t2;i++)
        sum2+=tr[tr[R[i]].l].sum;
    int mid=(l+r)>>1;
    if (sum2-sum1>=k)
    {
        for (int i=1;i<=t1;i++)
            L[i]=tr[L[i]].l;
        for (int i=1;i<=t2;i++)
            R[i]=tr[R[i]].l;
        return ask(l,mid,k);
    }else
    {
        for (int i=1;i<=t1;i++)
            L[i]=tr[L[i]].r;
        for (int i=1;i<=t2;i++)
            R[i]=tr[R[i]].r;
        return ask(mid+1,r,k-sum2+sum1);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        p[++tot]=a[i];
    }
    for (int i=1;i<=m;i++)
    {
        scanf("%s",s);
        if (s[0]=='C'){scanf("%d%d",&x[i],&y[i]);p[++tot]=y[i];}else
        {scanf("%d%d%d",&x[i],&y[i],&z[i]);}
    }
    sort(p+1,p+tot+1);
    tot=unique(p+1,p+tot+1)-p-1;
    for (int i=1;i<=n;i++)
    {
        a[i]=lower_bound(p+1,p+tot+1,a[i])-p;
        for (int j=i;j<=n;j+=((j)&(-j)))
            change(1,tot,root[j],a[i],1);
    }
    for (int i=1;i<=m;i++)
    {
        if (z[i])
        {
            x[i]--;
            t1=t2=0;
            for (int j=x[i];j;j-=((j)&(-j)))
                L[++t1]=root[j];
            for (int j=y[i];j;j-=((j)&(-j)))
                R[++t2]=root[j];
            printf("%d\n",p[ask(1,tot,z[i])]);
        }else
        {
            y[i]=lower_bound(p+1,p+tot+1,y[i])-p;
            for (int j=x[i];j<=n;j+=((j)&(-j)))
                change(1,tot,root[j],a[x[i]],-1);
            for (int j=x[i];j<=n;j+=((j)&(-j)))
                change(1,tot,root[j],y[i],1);
            a[x[i]]=y[i];
        }
    }
}
Category: 主席树 | Tags: | Read Count: 413

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com