• [bzoj1901]Zju2112 Dynamic Rankings


    给定数组,单点修改,区间查询k小。$(n leq 10000)$

    暴力题?挺暴力的。树状数组+动态开点线段树。

    树状数组维护每个权值的前缀和。可以视为是树状数组的每个节点开一个主席树吧。

    修改:修改树状数组上包含修改点的权值线段树。$O(log^2n)$

    查询:像主席树一样不断通过二分缩小区间,区间和变成用树状数组求。由于每次二分要查询的节点是一样的,需要维护这些节点的pointer跳到哪里。$O(log^2n)$话说我没维护这个是$O(log^3n)$的。。。Sinogi大佬写了!%%%比我快(长)很多!

    但是这种题n都10000了随便怎么做了吧,,,暴力貌似可过,,,尬

    #include<bits/stdc++.h>
    using namespace std;
    const int N=20010;
    inline int read(){
        int r=0,c=getchar();
        while(!isdigit(c))c=getchar();
        while(isdigit(c))
        r=r*10+c-'0',c=getchar();
        return r;
    }
    struct Node{
        int ls,rs,sum;
    }T[N*100];
    struct ask{
        int opt,l,r,k;
    }q[N];
    int rt[N],n,m,cnt;
    int a[N],b[N],tot,v;
    void upd(int &k,int l,int r,int val){
        if(!k)k=++cnt;
        T[k].sum+=v;
        if(l==r){
            return;
        }
        int mid=l+r>>1;
        if(val<=mid)upd(T[k].ls,l,mid,val);
        else upd(T[k].rs,mid+1,r,val);
    }
    void modify(int x,int w){
        w=lower_bound(b+1,b+tot+1,w)-b;
        for(int i=x;i<=n;i+=i&-i)
        upd(rt[i],1,tot,w);
    }
    int pt[N],L,R;
    int sum(int x,int l,int r){
        if(!x)return 0;
        if(L<=l&&r<=R){
            return T[x].sum;
        }
        int mid=l+r>>1,ans=0;
        if(L<=mid)ans+=sum(T[x].ls,l,mid);
        if(R>mid) ans+=sum(T[x].rs,mid+1,r);
        return ans;
    }
    int query(int l,int r){
        int ret=0;
        for(int i=r;i;i-=i&-i)
        ret+=sum(rt[i],1,tot);
        for(int i=l;i;i-=i&-i)
        ret-=sum(rt[i],1,tot);
        return ret;
    }
    void init(){
        n=read(),m=read();
        for(int i=1;i<=n;i++)
        a[i]=read(),b[++tot]=a[i];
        char s[5];
        for(int i=1;i<=m;i++){
            scanf("%s",s);
            if(s[0]=='C'){
                int x=read(),w=read();
                q[i]=(ask){0,x,x,w};
                b[++tot]=w;
            }
            else{
                int l=read(),r=read(),w=read();
                q[i]=(ask){1,l,r,w};
                b[++tot]=w;
            }
        }
        sort(b+1,b+tot+1);
        tot=unique(b+1,b+tot+1)-b-1;
    }
    void solve(){
        for(int i=1;i<=n;i++)
        v=1,modify(i,a[i]);
        for(int i=1;i<=m;i++){
            if(!q[i].opt){
                int x=q[i].l;
                v=-1;modify(x,a[x]);
                v=1;modify(x,a[x]=q[i].k);
            }
            else{
                int x=q[i].l-1,y=q[i].r,rk=q[i].k;
                int l=1,r=tot;
                while(l^r){
                    int mid=l+r>>1;
                    L=l,R=mid;
                    int t=query(x,y);
                    if(rk<=t)r=mid;
                    else l=mid+1,rk-=t;
                }
                printf("%d
    ",b[l]);
            }
        }
    }
    int main(){
        init();
        solve();
    }
  • 相关阅读:
    Lambda表达式
    多态之美
    集合那点事
    程序员艺术家
    MySQL:如何导入导出数据表和如何清空有外建关联的数据表
    Ubuntu修改桌面为Desktop
    shutil.rmtree()
    SCP命令
    kickstart
    数据哈希加盐
  • 原文地址:https://www.cnblogs.com/orzzz/p/8110994.html
Copyright © 2020-2023  润新知