zoukankan      html  css  js  c++  java
  • bzoj1901 Zju2112 Dynamic Rankings

    1901: Zju2112 Dynamic Rankings

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 8710  Solved: 3626
    [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
    分析:带修改的主席树.
              其实主席树就是维护前缀和的权值线段树.单点修改,要O(n)的时间修改前缀和.这样承受不起,需要优化.树状数组就是一个log复杂度维护前缀和的数据结构,那么这道题就可以树状数组套主席树.
              主席树每个点表示的是什么要搞清楚.在这道题中,主席树上的每个点代表在树状数组里的点,那么每次修改一个数i都要不停地加lowbit,修改第i棵树.查询同理.
              这样的话有一个问题:第i棵线段树不能在以前的树的基础上建立,因为在这里每棵树代表的不再是前缀,而是点.
              考虑本题的修改操作,先将原数在树状数组中删除,接着在树状数组中加上新的数.查询操作像树状数组一样,将要查询的根给提出来.注意离散化,要将修改操作的值离散化!
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 20010;
    
    int n,m,a[maxn],b[maxn],cnt,tot,ansx[maxn],ansy[maxn],cnt1,cnt2,root[maxn];
    
    struct node
    {
        int x,y,z,id;
    }e[maxn];
    
    struct node2
    {
        int left,right,sum;
    }tr[2200011];
    
    void update(int l,int r,int &x,int y,int pos,int v)
    {
        x = ++tot;
        tr[x] = tr[y];
        tr[x].sum += v;
        if (l == r)
            return;
        int mid = (l + r) >> 1;
        if (pos <= mid)
            update(l,mid,tr[x].left,tr[y].left,pos,v);
        else
            update(mid + 1,r,tr[x].right,tr[y].right,pos,v);
    }
    
    int query(int l,int r,int p)
    {
        if (l == r)
            return l;
        int mid = (l + r) >> 1;
        int res1 = 0,res2 = 0;
        for (int i = 1; i <= cnt1; i++)
            res1 += tr[tr[ansx[i]].left].sum;
        for (int i = 1; i <= cnt2; i++)
            res2 += tr[tr[ansy[i]].left].sum;
        if (p <= res2 - res1)
        {
            for (int j = 1; j <= cnt1; j++)
                ansx[j] = tr[ansx[j]].left;
            for (int j = 1; j <= cnt2; j++)
                ansy[j] = tr[ansy[j]].left;
            return query(l,mid,p);
        }
        else
        {
            for (int j = 1; j <= cnt1; j++)
                ansx[j] = tr[ansx[j]].right;
            for (int j = 1; j <= cnt2; j++)
                ansy[j] = tr[ansy[j]].right;
            return query(mid + 1,r,p - (res2 - res1));
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d",&a[i]);
            b[i] = a[i];
        }
        cnt = n;
        for (int i = 1; i <= m; i++)
        {
            char ch[2];
            scanf("%s",ch);
            if (ch[0] == 'Q')
            {
                scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
                e[i].x--;
                e[i].id = 1;
            }
            else
            {
                scanf("%d%d",&e[i].x,&e[i].y);
                e[i].id = 2;
                b[++cnt] = e[i].y;
            }
        }
        sort(b + 1,b + 1 + cnt);
        cnt = unique(b + 1,b + 1 + cnt) - b - 1;
        for (int i = 1; i <= n; i++)
        {
            int temp = lower_bound(b + 1,b + 1 + cnt,a[i]) - b;
            for (int j = i; j <= n; j += j & (-j))
                update(1,cnt,root[j],root[j],temp,1);
        }
        for (int i = 1; i <= m; i++)
        {
            if (e[i].id == 1)
            {
                cnt1 = cnt2 = 0;
                for (int j = e[i].x;j; j -= j & (-j))
                    ansx[++cnt1] = root[j];
                for (int j = e[i].y;j; j -= j & (-j))
                    ansy[++cnt2] = root[j];
                printf("%d
    ",b[query(1,cnt,e[i].z)]);
            }
            else
            {
                int temp = lower_bound(b + 1,b + 1 + cnt,a[e[i].x]) - b;
                for (int j = e[i].x; j <= n; j += j & (-j))
                    update(1,cnt,root[j],root[j],temp,-1);
                a[e[i].x] = e[i].y;
                temp = lower_bound(b + 1,b + 1 + cnt,e[i].y) - b;
                for (int j = e[i].x; j <= n; j += j & (-j))
                    update(1,cnt,root[j],root[j],temp,1);
            }
        }
    
        return 0;
    }
  • 相关阅读:
    设计模式——原型链模式之在原型上设置属性
    设计模式——原型链模式
    设计模式——构造函数模式
    设计模式——工厂模式
    设计模式——单例模式
    为什么做java的web开发我们会使用struts2,springMVC和spring这样的框架?(转载)
    Unity3d中设置UISprite图片灰显方法
    游戏后端主程工作内容及游戏项目中的注意事项及游戏项目中注意事项<转载>
    xcode使用
    ios学习笔记2
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8280803.html
Copyright © 2011-2022 走看看