• 【BZOJ】1901: Zju2112 Dynamic Rankings


    【题意】带修改的查询区间第k小

    【算法】树状数组套可持久化线段树

    【题解】对于树状数组上的每个节点,维护可持久化权值线段树(节点为权值),从而达到查询前缀和的目的。

    对于每次修改,在待修改线段树基础上运用可持久化性质来修改,先删除原数字,再加入新数字

    注意记录修改后的原数字,方便后来删除。

    ★注意区分权值范围和数组范围的区别!!!

    复杂度O(n log2n)。

    注意点全部标注在代码中,细节巨多。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    using namespace std;
    int read()
    {
        char c;int s=0,t=1;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s*t;
    }
    const int maxn=10010;
    struct tree{int l,r,sum;}t[10000010];//空间开大!!!100w都过不去啊。。。 
    char s[10];
    int cnt1,cnt2,a1[maxn],a2[maxn],a[maxn],b1[maxn],b2[maxn],b3[maxn],n,m,root[maxn],tot,c[maxn*2],sz=0;
    
    void insert(int l,int r,int x,int &y,int v,int c){
        y=++sz;//设置新节点!!! 
        t[y]=t[x];t[y].sum+=c;
        if(l==r)return;
        int mid=(l+r)>>1;
        if(v<=mid)insert(l,mid,t[x].l,t[y].l,v,c);
        else insert(mid+1,r,t[x].r,t[y].r,v,c);
    }
    int ask(int l,int r,int v){
        if(l==r)return l;
        int sum=0;
        for(int i=1;i<=cnt1;i++)sum-=t[t[a1[i]].l].sum;
        for(int i=1;i<=cnt2;i++)sum+=t[t[a2[i]].l].sum;
        int mid=(l+r)>>1;
        if(sum>=v){
            for(int i=1;i<=cnt1;i++)a1[i]=t[a1[i]].l;
            for(int i=1;i<=cnt2;i++)a2[i]=t[a2[i]].l;
            return ask(l,mid,v);
        }
        else{
            for(int i=1;i<=cnt1;i++)a1[i]=t[a1[i]].r;
            for(int i=1;i<=cnt2;i++)a2[i]=t[a2[i]].r;
            return ask(mid+1,r,v-sum);//转入右边要减去左边的 
        }
    }
        
    int lowbit(int x){return x&(-x);}
    void modify(int x,int k,int p){for(int i=x;i<=n;i+=lowbit(i))insert(1,tot,root[i],root[i],k,p);} 
    //分清,tot是权值线段树范围,n是数组范围 
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            a[i]=read();
            c[++tot]=a[i];
        }
        for(int i=1;i<=m;i++){
            scanf("%s%d%d",s,&b1[i],&b2[i]);
            if(s[0]=='Q')b3[i]=read();
            else c[++tot]=b2[i];
        }
        sort(c+1,c+tot+1);
        tot=unique(c+1,c+tot+1)-c-1;
        for(int i=1;i<=n;i++)a[i]=lower_bound(c+1,c+tot+1,a[i])-c;
        for(int i=1;i<=m;i++)if(!b3[i])b2[i]=lower_bound(c+1,c+tot+1,b2[i])-c;
        for(int i=1;i<=n;i++)modify(i,a[i],1);
        for(int i=1;i<=m;i++){
            if(b3[i]){
                cnt1=0;cnt2=0;
                for(int j=b1[i]-1;j>=1;j-=lowbit(j))a1[++cnt1]=root[j];
                for(int j=b2[i];j>=1;j-=lowbit(j))a2[++cnt2]=root[j];//用根啊老铁 
                printf("%d
    ",c[ask(1,tot,b3[i])]);//询问给的是离散化后的值,要还原 
            }
            else{
                modify(b1[i],a[b1[i]],-1);
                a[b1[i]]=b2[i];
                modify(b1[i],b2[i],1);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    解决ffmpeg打开流各种超时问题
    ffmpeg函数使用
    如何从AVFrame::data【0】里获取RGB24数据和YUYV422数据
    ffmpeg取rtsp流时av_read_frame阻塞的解决办法
    FFMPEG实时解码网络视频流(回调方式)
    JavaScript 演练(7). 赋值与引用
    JavaScript 演练(5). 模拟类
    曾经对 TMemoryStream.Memory 错误的理解
    JavaScript 演练(10). 谁的 this ?
    JavaScript 演练(6). 函数的定义与自执行
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7388920.html
Copyright © 2020-2023  润新知