1901: Zju2112 Dynamic Rankings

1901: Zju2112 Dynamic Rankings

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 7339  Solved: 3055
[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。

Source

 
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+5;
const int M=2200001;
int n,m,cnt,top,a,b,X[N],A[N],B[N],v[N],num[N<<1],K[N],L[30],R[30];
int root[N],ls[M],rs[M],sum[M];
int lowbit(int x){
    return x&-x;
}
void insert(int &k,int last,int l,int r,int x,int add){
    k=++cnt;
    int mid=l+r>>1;
    ls[k]=ls[last];
    rs[k]=rs[last];
    sum[k]=sum[last]+add;
    if(l==r) return;
    if(x<=mid) insert(ls[k],ls[last],l,mid,x,add);
    else insert(rs[k],rs[last],mid+1,r,x,add);
}
     
int query(int l,int r,int k){
    if(l==r) return l;
    int mid=l+r>>1;
    int suml=0,sumr=0;
    for(int i=1;i<=a;i++)suml+=sum[ls[L[i]]];
    for(int i=1;i<=b;i++)sumr+=sum[ls[R[i]]];
    if(sumr-suml>=k){
        for(int i=1;i<=a;i++) L[i]=ls[L[i]];
        for(int i=1;i<=b;i++) R[i]=ls[R[i]];
        return query(l,mid,k);
    }
    else{
        for(int i=1;i<=a;i++) L[i]=rs[L[i]];
        for(int i=1;i<=b;i++) R[i]=rs[R[i]];
        return query(mid+1,r,k-(sumr-suml));
    }
}
     
int main(){
    scanf("%d%d",&n,&m);top=n;
    for(int i=1;i<=n;i++) scanf("%d",&v[i]),num[i]=v[i];
    char opt[6];
    for(int i=1;i<=m;i++){
        scanf("%s%d%d",opt,&A[i],&B[i]);
        if(opt[0]=='Q') scanf("%d",&X[i]),K[i]=1;
        else num[++top]=B[i];
    }
    sort(num+1,num+top+1);
    int tot=unique(num+1,num+top+1)-num-1;
    for(int i=1;i<=n;i++){
        int t=lower_bound(num+1,num+tot+1,v[i])-num;
        for(int j=i;j<=n;j+=lowbit(j))
            insert(root[j],root[j],1,tot,t,1);
    }
    for(int i=1;i<=m;i++){
        if(K[i]){
            a=0,b=0;A[i]--;
            for(int j=A[i];j>=1;j-=lowbit(j)) L[++a]=root[j];
            for(int j=B[i];j>=1;j-=lowbit(j)) R[++b]=root[j];
            printf("%d
",num[query(1,tot,X[i])]);
        }
        else{
            int t=lower_bound(num+1,num+tot+1,v[A[i]])-num;
            for(int j=A[i];j<=n;j+=lowbit(j)) 
            insert(root[j],root[j],1,tot,t,-1);
            v[A[i]]=B[i];
            t=lower_bound(num+1,num+tot+1,v[A[i]])-num;
            for(int j=A[i];j<=n;j+=lowbit(j)) 
            insert(root[j],root[j],1,tot,t,1);
        }
    }
}

分块代码

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
template <typename T>
inline void read(T &x){
    T f=1;char ch=getchar();x=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    x*=f;
}
inline char in(){
    for(char ch=getchar();;ch=getchar()) if(ch>='A'&&ch<='Z') return ch;
}
const int N=1e5+5;
int n,m,bsize,a[N],b[N],bl[N];char op;
inline void init(int id){
    sort(b+(id-1)*bsize+1,b+min(id*bsize,n)+1);
}
inline void change(int x,int y){
    (*lower_bound(b+(bl[x]-1)*bsize+1,b+min(bl[x]*bsize,n)+1,a[x]))=y;
    sort(b+(bl[x]-1)*bsize+1,b+min(bl[x]*bsize,n)+1);
    a[x]=y;
}
int nownum;
#define calc res+=a[i]<now,nownum+=a[i]==now;
inline int count_num(int x,int y,int now){
    int res=0;nownum=0;
    if(bl[x]==bl[y]){
        for(int i=x;i<=y;i++) calc
    }
    else{
        for(int i=x;i<=bl[x]*bsize;i++) calc
        for(int i=(bl[y]-1)*bsize+1;i<=y;i++) calc
        for(int i=bl[x]+1,p1,p2,l,r;i<bl[y];i++){
            l=(i-1)*bsize+1;
            r=min(i*bsize,n);
            p1=lower_bound(b+l,b+r+1,now)-(b+l);
            p2=upper_bound(b+l,b+r+1,now)-(b+l);
            res+=p1;
            nownum+=p2-p1;
        }
    }
    return res;
}
int mx,mn;
#define maxmin mx=max(mx,a[i]),mn=min(mn,a[i]);
inline int range(int x,int y){
    mx=-2e9;mn=2e9;
    if(bl[x]==bl[y]){
        for(int i=x;i<=y;i++) maxmin
    }
    else{
        for(int i=x;i<=bl[x]*bsize;i++) maxmin
        for(int i=(bl[y]-1)*bsize+1;i<=y;i++) maxmin
        for(int i=bl[x]+1,p,l,r;i<bl[y];i++){
            l=(i-1)*bsize+1;
            r=min(i*bsize,n);
            mx=max(mx,b[r]);
            mn=min(mn,b[l]);
        }
    }
}
inline int query(int x,int y,int k){
    range(x,y);
    int l=mn,r=mx,mid,less;
    while(l<=r){
        mid=l+r>>1;
        less=count_num(x,y,mid);
        if(less+1<=k&&less+nownum>=k) return mid;
        if(less>=k)
            r=mid-1;
        else
            l=mid+1;
    }
    return l;
}
int main(){
    read(n);read(m);bsize=sqrt(n+0.5);
    for(int i=1;i<=n;i++) read(a[i]),b[i]=a[i];
    for(int i=1;i<=n;i++) bl[i]=(i-1)/bsize+1;
    for(int i=1;i<=bl[n];i++) init(i);
    for(int i=1,x,y,z;i<=m;i++){
        op=in();read(x),read(y);
        if(op=='C') change(x,y);
        if(op=='Q') read(z),printf("%d
",query(x,y,z));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shenben/p/6281390.html