• ZOJ2112--Dynamic Rankings (动态区间第k大)


    Dynamic Rankings

    Time Limit: 10 Seconds      Memory Limit: 32768 KB

    The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They have developed a more powerful system such that for N numbers a[1], a[2], ..., a[N], you can ask it like: what is the k-th smallest number of a[i], a[i+1], ..., a[j]? (For some i<=j, 0<k<=j+1-i that you have given to it). More powerful, you can even change the value of some a[i], and continue to query, all the same.

    Your task is to write a program for this computer, which

    - Reads N numbers from the input (1 <= N <= 50,000)

    - Processes M instructions of the input (1 <= M <= 10,000). These instructions include querying the k-th smallest number of a[i], a[i+1], ..., a[j] and change some a[i] to t.


    Input

    The first line of the input is a single number X (0 < X <= 4), the number of the test cases of the input. Then X blocks each represent a single test case.

    The first line of each block contains two integers N and M, representing N numbers and M instruction. It is followed by N lines. The (i+1)-th line represents the number a[i]. Then M lines that is in the following format

    Q i j k or
    C i t

    It represents to query the k-th number of a[i], a[i+1], ..., a[j] and change some a[i] to t, respectively. It is guaranteed that at any time of the operation. Any number a[i] is a non-negative integer that is less than 1,000,000,000.

    There're NO breakline between two continuous test cases.


    Output

    For each querying operation, output one integer to represent the result. (i.e. the k-th smallest number of a[i], a[i+1],..., a[j])

    There're NO breakline between two continuous test cases.


    Sample Input

    2
    5 3
    3 2 1 4 7
    Q 1 4 3
    C 2 6
    Q 2 5 3
    5 3
    3 2 1 4 7
    Q 1 4 3
    C 2 6
    Q 2 5 3


    Sample Output

    3
    6
    3
    6

    主席树动态第k大基本可以手写,,但是感觉理解还不是很深。另外定义两个数组,一个用来新建一颗主席树,所有修改的结果都在这个上面进行,而另一个是记录中间值,相当于temp的效果,不改变原始数组。。(挖个坑)

    附主席树专题链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=63941#overview

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <iostream>
      6 using namespace std;
      7 typedef long long ll;
      8 const int maxn = 5e4+10;
      9 int n,m,tot,idx;
     10 ll a[maxn],vec[maxn*2];
     11 struct
     12 {
     13     int x,y,k,flag,idx;
     14 } Q[maxn];
     15 
     16 //   主席树
     17 int lson[maxn*50],rson[maxn*50],c[maxn*50],root[maxn]; //依次为左儿子 右儿子 线段树  根节点
     18 int build (int l,int r)
     19 {
     20     int root = tot++;
     21     c[root] = 0;
     22     if (l != r)
     23     {
     24         int mid = (l + r) >> 1;
     25         lson[root] = build(l,mid);
     26         rson[root] = build(mid+1,r);
     27     }
     28     return root;
     29 }
     30 int update(int root,int pos,int val)
     31 {
     32     int new_root = tot++;
     33     int tmp = new_root;
     34     int l = 1,r = idx;
     35     c[new_root] = c[root] + val;
     36     while (l < r)
     37     {
     38         int mid = (l + r) >> 1;
     39         if (pos <= mid)
     40         {
     41             rson[new_root] = rson[root];
     42             root = lson[root];
     43             lson[new_root] = tot++;
     44             new_root = lson[new_root];
     45             r = mid;
     46         }
     47         else
     48         {
     49             lson[new_root] = lson[root];
     50             root = rson[root];
     51             rson[new_root] = tot++;
     52             new_root = rson[new_root];
     53             l = mid + 1;
     54         }
     55         c[new_root] = c[root] + val;
     56     }
     57     return tmp;
     58 }
     59 //  树状数组维护
     60 int s[maxn],use[maxn];
     61 inline int lowbit (int x)
     62 {
     63     return x & -x;
     64 }
     65 void add(int k,int pos,int d)
     66 {
     67     while (k <= n)
     68     {
     69         s[k] = update(s[k],pos,d);
     70         k += lowbit(k);
     71     }
     72 }
     73 int sum(int pos)
     74 {
     75     int res = 0;
     76     while (pos)
     77     {
     78         res += c[lson[use[pos]]];
     79         pos -= lowbit(pos);
     80     }
     81     return res;
     82 }
     83 int query(int left,int right,int k)
     84 {
     85     int l_root = root[left-1];
     86     int r_root = root[right];
     87     for (int i = left-1; i > 0; i -= lowbit(i))
     88         use[i] = s[i];
     89     for (int i = right; i > 0; i -= lowbit(i))
     90         use[i] =s[i];
     91     int l = 1,r = idx;
     92     while (l < r)
     93     {
     94         int t = sum(right) - sum(left-1) + c[lson[r_root]] - c[lson[l_root]];
     95         int mid = (l + r) >> 1;
     96         if (t >= k)
     97         {
     98             for (int i = left-1; i > 0; i -= lowbit(i))
     99                 use[i] = lson[use[i]];
    100             for (int i = right; i > 0; i -= lowbit(i))
    101                 use[i] = lson[use[i]];
    102             l_root = lson[l_root];
    103             r_root = lson[r_root];
    104             r = mid;
    105         }
    106         else
    107         {
    108             for (int i = left-1; i > 0; i -= lowbit(i))
    109                 use[i] = rson[use[i]];
    110             for (int i = right; i > 0; i -= lowbit(i))
    111                 use[i] = rson[use[i]];
    112             l_root = rson[l_root];
    113             r_root = rson[r_root];
    114             k -= t;
    115             l = mid + 1;
    116         }
    117     }
    118     return l;
    119 }
    120 
    121 void read()
    122 {
    123     scanf ("%d%d",&n,&m);
    124     for (int i = 1; i <= n; i++)
    125     {
    126         scanf ("%lld",a+i);
    127         vec[idx++] = a[i];
    128     }
    129     for (int i = 0; i < m; i++)
    130     {
    131         char op[3];
    132         scanf ("%s",op);
    133         if (op[0] == 'C')
    134         {
    135             scanf ("%d%d",&Q[i].x,&Q[i].y);
    136             Q[i].flag = 0;
    137             vec[idx++] = Q[i].y;
    138         }
    139         if (op[0] == 'Q')
    140         {
    141             scanf ("%d%d%d",&Q[i].x,&Q[i].y,&Q[i].k);
    142             Q[i].flag = 1;
    143         }
    144     }
    145 }
    146 int main(void)
    147 {
    148 #ifndef ONLINE_JUDGE
    149     freopen("in.txt","r",stdin);
    150 #endif
    151     int T;
    152     scanf ("%d",&T);
    153     while (T--)
    154     {
    155         idx = tot = 0;
    156         read();
    157         sort(vec,vec+idx);                   //离散化
    158         idx = unique(vec,vec+idx) - vec;
    159         root[0] = build(1,idx);
    160         for (int i = 1; i <= n; i++)
    161         {
    162             int tmp = lower_bound(vec,vec+idx,a[i]) - vec ;
    163             root[i] = update(root[i-1],tmp,1);
    164         }
    165         for (int i = 0; i <= n; i++)
    166             s[i] = root[0];
    167         for (int i = 0; i < m; i++)
    168         {
    169             if (Q[i].flag == 0)
    170             {
    171                 int tmp1 = lower_bound(vec,vec+idx,a[Q[i].x]) - vec ;
    172                 int tmp2 = lower_bound(vec,vec+idx,Q[i].y) - vec ;
    173                 add(Q[i].x,tmp1,-1);
    174                 add(Q[i].x,tmp2,1);
    175                 a[Q[i].x] = Q[i].y;
    176             }
    177             if (Q[i].flag == 1)
    178             {
    179                 printf("%lld
    ",vec[query(Q[i].x,Q[i].y,Q[i].k)]);
    180             }
    181         }
    182     }
    183     return 0;
    184 }
  • 相关阅读:
    约数个数 和 约数之和
    二分模板
    新生赛补题
    codefores刷题心得3 思维+dp(特别好玩)
    二叉树的遍历及例题
    团队作业七——团队作业分配
    WarPlane——游戏设计文档
    团队作业(五)
    团队作业(四)
    团队项目方案分析
  • 原文地址:https://www.cnblogs.com/oneshot/p/4119616.html
Copyright © 2020-2023  润新知