• Hdu CRB and Queries(整体二分)


    CRB and Queries
    Time Limit: 6000 MS Memory Limit: 131072 K
    Problem Description
    There are N boys in CodeLand.
    Boy i has his coding skill Ai.
    CRB wants to know who has the suitable coding skill.
    So you should treat the following two types of queries.
    Query 1: 1 l v
    The coding skill of Boy l has changed to v.
    Query 2: 2 l r k
    This is a report query which asks the k-th smallest value of coding skill between Boy l and Boy r(both inclusive).
    Input
    There are multiple test cases.
    The first line contains a single integer N.
    Next line contains N space separated integers A1, A2, …, AN, where Ai denotes initial coding skill of Boy i.
    Next line contains a single integer Q representing the number of queries.
    Next Q lines contain queries which can be any of the two types.
    1 ≤ N, Q ≤ 105
    1 ≤ Ai, v ≤ 109
    1 ≤ l ≤ r ≤ N
    1 ≤ k ≤ r – l + 1
    Output
    For each query of type 2, output a single integer corresponding to the answer in a single line.
    Sample Input
    5
    1 2 3 4 5
    3
    2 2 4 2
    1 3 6
    2 2 4 2
    Sample Output
    3
    4
    Author
    KUT(DPRK)
    Source
    2015 Multi-University Training Contest 10

    /*
    动态区间第K小.
    把操作离线.
    修改操作视为一个删除操作和一个添加操作.
    然后和静态处理方式相同. 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MAXN 400001
    #define INF 1e9
    using namespace std;
    struct data{int x,y,k,s,o,cut;}
    q[MAXN],tmp1[MAXN],tmp2[MAXN];
    int n,m,tot,cut,s[MAXN],ans[MAXN],a[MAXN],tmp[MAXN];
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
        return x*f;
    }
    void add(int x,int z)
    {
        while(x<=n) s[x]+=z,x+=x&-x;
        return ;
    }
    int getsum(int x)
    {
        int sum=0;
        while(x>0) sum+=s[x],x-=x&-x;
        return sum;
    }
    void slove(int head,int tail,int l,int r)
    {
        if(head>tail) return ;
        if(l==r)
        {
            for(int i=head;i<=tail;i++)
              if(q[i].o==3) ans[q[i].s]=l;
            return ;
        }
        int mid=(l+r)>>1;
        for(int i=head;i<=tail;i++)//统计贡献.
        {
            if(q[i].o==1&&q[i].y<=mid) add(q[i].x,1);
            else if(q[i].o==2&&q[i].y<=mid) add(q[i].x,-1);
            else if(q[i].o==3) tmp[i]=getsum(q[i].y)-getsum(q[i].x-1);
        }
        for(int i=head;i<=tail;i++)
        {
            if(q[i].y<=mid)
            {
                if(q[i].o==1) add(q[i].x,-1);
                else if(q[i].o==2) add(q[i].x,1);
            }
        }
        int l1=0,l2=0;
        for(int i=head;i<=tail;i++)
        {
            if(q[i].o==3)
            {
                if(q[i].cut+tmp[i]>q[i].k-1) tmp1[++l1]=q[i];
                //对于该操作找一个所属答案位置.
                else q[i].cut+=tmp[i],tmp2[++l2]=q[i];
            }
            else
            {
                if(q[i].y<=mid) tmp1[++l1]=q[i];
                else tmp2[++l2]=q[i];
            }
        }
        for(int i=1;i<=l1;i++) q[head+i-1]=tmp1[i];
        for(int i=1;i<=l2;i++) q[head+l1+i-1]=tmp2[i];
        slove(head,head+l1-1,l,mid),slove(head+l1,tail,mid+1,r);
        return ;
    }
    void Clear()
    {
        memset(q,0,sizeof q);
        //memset(s,0,sizeof s);
        //memset(ans,0,sizeof ans);
        tot=cut=0;return ;
    }
    int main()
    {
    
        int x,y,z,k;
        while(scanf("%d",&n)!=EOF)
        {
            Clear();
            for(int i=1;i<=n;i++)
            {
                a[i]=read();
                q[++tot].x=i,q[tot].y=a[i];
                q[tot].o=1,q[tot].s=0;
            }
            m=read();
            while(m--)
            {
                z=read();
                if(z==2)
                {
                    x=read(),y=read(),k=read();
                    q[++tot].x=x,q[tot].y=y,q[tot].k=k;
                    q[tot].o=3;q[tot].s=++cut;
                }
                else
                {
                    x=read(),y=read();
                    q[++tot].x=x,q[tot].y=a[x];
                    q[tot].o=2,q[tot].s=0;
                    q[++tot].x=x,q[tot].y=y;
                    q[tot].o=1,q[tot].s=0;
                    a[x]=y;
                }
            }
            slove(1,tot,-INF,INF);
            for(int i=1;i<=cut;i++) printf("%d
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    Ubuntu 32下Android NDK+NEON的配置过程及简单使用举例
    java环境变量配置
    实现TextView 文字排版,分散两端对齐
    cmd 控制台 提示:请求的操作须要提升!
    怎样将程序猿写出来的程序打包成安装包(最简单的)
    二分查找
    32位Linux文件限制大小
    Windows ICS 服务无法启动问题解决
    Microsoft.AlphaImageLoader滤镜解说
    memset函数具体说明
  • 原文地址:https://www.cnblogs.com/nancheng58/p/10068068.html
Copyright © 2020-2023  润新知