zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    一年足迹记录
    Scanf连续调用多次并且存在%c的问题
    Oracle学习计划
    SQL语句、PL/SQL语句、SQL*PLUS语句结束符号
    使用sys无法通过sqlplus或者sqldeveloper连接数据库
    把十进制转化为二进制的一种方法
    GTK+与QT的对比
    数据库崩溃后对redo log的使用
    产生不重复的随机牌
    失效试图,还有就是 还原试图。
  • 原文地址:https://www.cnblogs.com/shenben/p/6281390.html
Copyright © 2011-2022 走看看