zoukankan      html  css  js  c++  java
  • BZOJ1901: Zju2112 Dynamic Rankings

    题解:  一般来说 一眼带修主席树...主席树+树状数组 2个log常规操作  刚开了整体二分 发现整体二分也是很顺手的 整体二分思想不复杂 类似于cdq那样分治离线考虑贡献 因为这题设计到修改操作 所以我们可以将修改拆成删去和加入元素即可 用两个树状数组维护答案即可

    树套树版本

    /**************************************************************
        Problem: 1901
        User: c20161007
        Language: C++
        Result: Accepted
        Time:384 ms
        Memory:48896 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    const int MAXN=2e4+10;
    using namespace std;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    typedef struct node{
        int l,r,sum;
    }node;
    node d[MAXN*201];
    int rt[MAXN];
    int cnt;
    int get_id(int x){return x&(-x);}
    void update(int &x,int y,int l,int r,int t,int vul){
        x=++cnt;d[x]=d[y];d[x].sum+=vul;
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(t<=mid)update(d[x].l,d[y].l,l,mid,t,vul);
        else update(d[x].r,d[y].r,mid+1,r,t,vul);
    }
    int ans,sum;
    vector<int>v1;
    vector<int>v2;
    void querty(int l,int r,int k){
        if(l==r){ans=l;return ;}
        sum=0;
        int mid=(l+r)>>1;
        for(int i=0;i<v1.size();i++)sum+=d[d[v1[i]].l].sum;
        for(int i=0;i<v2.size();i++)sum-=d[d[v2[i]].l].sum;
       // cout<<l<<" "<<r<<" "<<sum<<endl;
        if(k<=sum){
        for(int i=0;i<v1.size();i++)v1[i]=d[v1[i]].l;
        for(int i=0;i<v2.size();i++)v2[i]=d[v2[i]].l;
        querty(l,mid,k);
        }
        else{
        for(int i=0;i<v1.size();i++)v1[i]=d[v1[i]].r;
        for(int i=0;i<v2.size();i++)v2[i]=d[v2[i]].r;
        querty(mid+1,r,k-sum);
        }
    }
    vector<int>vec;
    int a[MAXN];
    typedef struct Q{
        int op,l,r,k;
    }Q;
    Q q[MAXN];
    int main(){
        int n,m;n=read();m=read();
        for(int i=1;i<=n;i++)a[i]=read(),vec.push_back(a[i]);
        char ch;
        for(int i=1;i<=m;i++){
        scanf(" %c",&ch);
        if(ch=='Q'){q[i].op=1;q[i].l=read();q[i].r=read();q[i].k=read();}
        else{q[i].op=2;q[i].l=read();q[i].r=read();vec.push_back(q[i].r);}
        }
        sort(vec.begin(),vec.end());
        int sz=unique(vec.begin(),vec.end())-vec.begin();
        for(int i=1;i<=n;i++){
        a[i]=lower_bound(vec.begin(),vec.begin()+sz,a[i])-vec.begin()+1;
    //  cout<<a[i]<<" ";
        for(int j=i;j<=n;j+=get_id(j))update(rt[j],rt[j],1,sz,a[i],1);
    //  cout<<endl;
        }
    //    cout<<endl;
        for(int i=1;i<=m;i++){
        if(q[i].op==2){
            q[i].r=lower_bound(vec.begin(),vec.begin()+sz,q[i].r)-vec.begin()+1;
            for(int j=q[i].l;j<=n;j+=get_id(j))update(rt[j],rt[j],1,sz,a[q[i].l],-1),update(rt[j],rt[j],1,sz,q[i].r,1);
            a[q[i].l]=q[i].r;
        }
        else{
            v1.clear();v2.clear();
    //      cout<<q[i].l<<" "<<q[i].r<<" "<<q[i].k<<endl;
            for(int j=q[i].r;j>0;j-=get_id(j))v1.push_back(rt[j]);
           // cout<<endl;
            for(int j=q[i].l-1;j>0;j-=get_id(j))v2.push_back(rt[j]);
           // cout<<endl;
            querty(1,sz,q[i].k);
            printf("%d
    ",vec[ans-1]);
        }
        }
        return 0;
    }
    
    

     整体二分版本:

    /**************************************************************
        Problem: 1901
        User: c20161007
        Language: C++
        Result: Accepted
        Time:292 ms
        Memory:2112 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    const int MAXN=1e4+10;
    const int inf=1e9;
    using namespace std;
    int n,m;
    int b[MAXN],id[MAXN<<1];
    typedef struct node{
        int l,r,k,ans,cnt;
    }node;
    node que[MAXN<<1];
    typedef struct Node{
        int pos,vul;
        friend bool operator<(Node aa,Node bb){return aa.vul<bb.vul;}
    }Node;
    Node a[MAXN];
    int get_id(int x){return x&(-x);}
    int sum[MAXN];
    void update(int x,int vul){
        for(int i=x;i<=n;i+=get_id(i))sum[i]+=vul;
    } 
    int Sum(int x){
        int sum1=0;
        for(int i=x;i>0;i-=get_id(i))sum1+=sum[i];
        return sum1;
    }
    int num[MAXN];
    void update1(int x,int vul){
        for(int i=x;i<=n;i+=get_id(i))num[i]+=vul;
    } 
    int Sum1(int x){
        int sum1=0;
        for(int i=x;i>0;i-=get_id(i))sum1+=num[i];
        return sum1;
    }
    int querty(int t){return Sum(que[t].r)-Sum(que[t].l-1);}
    int querty1(int t){return Sum1(que[t].r)-Sum1(que[t].l-1);}
    int tot;
    int ed[MAXN<<1],ip[MAXN<<1];
    void slove(int ql,int qr,int l,int r){
        if(ql>qr||l==r)return ;
        //cout<<l<<" "<<r<<endl;
        int mid=(l+r)>>1;
        int cnt=0,cnt1=0;
        while(tot<n&&a[tot+1].vul<=mid){
            tot++;
            update(a[tot].pos,1);
        }
        while(tot&&a[tot].vul>mid){
            update(a[tot].pos,-1);
            tot--;
        }
        //cout<<tot<<" "<<mid<<endl;
        for(int i=ql;i<=qr;i++){
            //cout<<que[id[i]].l<<":::::"<<que[id[i]].r<<" "<<que[id[i]].ans<<endl;
            if(que[id[i]].k==0){
                if(que[id[i]].ans<=mid)update1(que[id[i]].l,que[id[i]].r);
                if(que[id[i]].ans<=mid)ed[++cnt]=id[i];
                else ip[++cnt1]=id[i];
            }
            else{
                //cout<<que[id[i]].l<<"==="<<que[id[i]].r<<" "<<querty(id[i])<<endl;
                if(querty(id[i])+que[id[i]].cnt+querty1(id[i])>=que[id[i]].k)ed[++cnt]=id[i],que[id[i]].ans=mid;
                else ip[++cnt1]=id[i],que[id[i]].cnt+=querty1(id[i]);
            }
        }
        for(int i=ql;i<=qr;i++)if(que[id[i]].k==0&&que[id[i]].ans<=mid)update1(que[id[i]].l,-1*que[id[i]].r);
        for(int i=1;i<=cnt;i++)id[ql+i-1]=ed[i];
        for(int i=1;i<=cnt1;i++)id[ql+cnt+i-1]=ip[i];
        slove(ql,ql+cnt-1,l,mid);
        slove(ql+cnt,qr,mid+1,r);
    }
    int main(){
        scanf("%d%d",&n,&m);tot=0;
        for(int i=1;i<=n;i++)scanf("%d",&b[i]),a[i]=(Node){i,b[i]};
        int l,r,k;char ch;int cnt=0;
        for(int i=1;i<=m;i++){
            scanf(" %c",&ch);scanf("%d%d",&l,&r);
            if(ch=='Q')scanf("%d",&k),que[++cnt]=(node){l,r,k,0},id[cnt]=cnt;
            else que[++cnt]=(node){l,-1,0,b[l]},id[cnt]=cnt,que[++cnt]=(node){l,1,0,r},b[l]=r,id[cnt]=cnt;
        }
        sort(a+1,a+n+1);
        slove(1,cnt,0,inf);
        for(int i=1;i<=cnt;i++)if(que[i].k!=0)printf("%d
    ",que[i].ans);
        return 0;
    }
    

    1901: Zju2112 Dynamic Rankings

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 9144  Solved: 3828
    [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继续回答上面的问题。

    Input

    第一行有两个正整数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
    m,n≤10000

    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

    Source

  • 相关阅读:
    RobotFramework 安装配置(一)
    JAVA练手--集合
    JAVA文件操作
    线性布局--LinearLayout
    android studio导入android studio工程
    通过开机广播(broadcast)通知应用
    Android studio应用导入源码错误This attribute must be localized
    android studio的jni和so
    上传漏洞总结-UPLOAD-LABS
    靶机渗透测试实战(一)——熟悉渗透测试流程的简单测试
  • 原文地址:https://www.cnblogs.com/wang9897/p/9464283.html
Copyright © 2011-2022 走看看