zoukankan      html  css  js  c++  java
  • ZOJ2112 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

    树套树做的真是excited。

    比较难理解的就是要把树状数组里面的元素看出一棵树,虽然这句话看着很好懂,但实际上码代码是必须时时提醒自己,否则太容易写错了。

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 using namespace std;
      6 const int N = 50000 + 11 , M = 10000 + 11 ;
      7 struct node
      8 {
      9     int sum ;
     10     int l , r;
     11     
     12 } tree[N*40] ;
     13 int bit[N] ,root[N] , use[N] , tot;
     14 int t , n , m , cnt , a[N], b[N+M];
     15 struct id
     16 {
     17     bool op;
     18     int l , r , k ;
     19 } que[M] ;
     20 
     21 void Init( )
     22 {
     23     cnt =  root[0] = root[1] = tot = 0 ;
     24     scanf("%d%d",&n,&m); 
     25     for(int x = 1 ; x <= n ; ++x) scanf("%d",a+x) , b[x] = a[x];
     26     char ch[3]; tot  = n ;
     27     for( int x = 1 ; x <= m ; ++x )
     28     {
     29         scanf("%s",ch);
     30         if(ch[0] == 'Q') que[x].op = false , scanf("%d%d%d",&que[x].l,&que[x].r,&que[x].k);
     31         else
     32         que[x].op = true , scanf("%d%d",&que[x].l,&que[x].k) , b[++tot] = que[x].k;
     33     }
     34     sort(b + 1 , b + 1 + tot);
     35     int now = tot ; tot = 1 ;
     36     for( int x = 2 ; x <= now ; ++x ) if( b[x] != b[tot] ) b[++tot] = b[x];
     37 }
     38 
     39 int binary_search( int num )
     40 {
     41     int l = 1 , r = tot ;
     42     while( l <= r )
     43     {
     44         int mid = l + ((r-l)>>1);
     45         if( b[mid] == num ) return mid;
     46         if( b[mid] < num ) l = mid + 1 ;
     47         else r = mid - 1;
     48     }
     49     return -1;
     50 }
     51 
     52 void updata( int l , int r , int &x , int y , int pos , int c )
     53 {
     54     tree[++cnt] = tree[y] , x = cnt , tree[cnt].sum += c ;
     55     if( l == r ) return ;
     56     int mid = l + ((r-l)>>1);
     57     if( pos <= mid ) updata(l,mid,tree[x].l,tree[y].l,pos,c);
     58     else updata(mid+1,r,tree[x].r,tree[y].r,pos,c);
     59 }
     60 
     61 int lowbit( int x ) { return x & -x; }
     62 
     63 int Sum( int x )
     64 {
     65     int ret = 0 ;
     66     for( int i = x ; i  > 0 ; i -= lowbit(i)) ret += tree[tree[use[i]].l].sum;
     67     return ret ;
     68 }
     69 
     70 int queryf(int l,int r,int k)
     71 {
     72     int L = 1 , R = tot , root_l = root[l] , root_r = root[r];
     73     for(int i = l ; i; i -= lowbit(i) ) use[i] = bit[i];
     74     for(int i = r ; i; i -= lowbit(i)) use[i] = bit[i] ;
     75     while(L <= R)
     76     {
     77         if( L == R ) return L ;
     78         int mid = L+((R-L)>>1);
     79         int tmp = Sum(r) - Sum(l) + tree[tree[root_r].l].sum - tree[tree[root_l].l].sum;
     80         if(tmp >= k)
     81         {
     82             R = mid;
     83             for(int i = l ; i ; i -= lowbit(i) ) use[i] = tree[use[i]].l ;
     84             for(int i = r; i ; i -= lowbit(i)) use[i] = tree[use[i]].l;
     85             root_l = tree[root_l].l , root_r = tree[root_r].l;
     86         }
     87         else
     88         {
     89             L = mid + 1 ;
     90             for(int i = l ; i ; i -= lowbit(i)) use[i] = tree[use[i]].r;
     91             for(int i = r ; i ; i -= lowbit(i)) use[i] = tree[use[i]].r;
     92             k -= tmp; root_l = tree[root_l].r , root_r = tree[root_r].r;         
     93         }  
     94     }
     95 
     96 }
     97 
     98 void insert( int x , int pos, int c )
     99 {
    100     for( int i = x ; i <= n; i += lowbit(i) )
    101         updata(1,tot,bit[i],bit[i],pos,c);
    102 }
    103 
    104 void Solve( )
    105 {
    106     for( int x = 1 ; x <= n ; ++x ) updata( 1 , tot , root[x] , root[x-1] , binary_search(a[x]) , 1 ) ;
    107     for(int i = 1; i <= n; i++) bit[i] = root[0]; 
    108     for( int x = 1 ; x <= m ; ++x )
    109     {
    110         if(!que[x].op) printf("%d
    ",b[queryf(que[x].l - 1 , que[x].r , que[x].k)]) ;
    111         else
    112         {
    113             insert(que[x].l,binary_search(a[que[x].l]),-1);
    114             insert(que[x].l,binary_search(que[x].k),1);
    115             a[que[x].l] = que[x].k;
    116         }
    117     }
    118 }
    119 
    120 int main()
    121 {
    122     scanf("%d",&t);
    123     while(t--) 
    124     {
    125         Init();
    126         Solve();
    127     } 
    128       return 0;
    129 }
  • 相关阅读:
    Public Sale(巴什博弈)
    Harmonic Value Description (思维+找规律)
    放苹果+N的划分(青理工校赛J题) (动归)
    线段树求逆序数+北化校赛D题
    写给自己
    Euclid's Game (博弈论)
    Bear and Blocks (dp+思维)
    Maximum splitting(找规律+思维)
    Bone Collector II(DP+第K优解)
    Codeforces 950E Data Center Maintenance ( 思维 && 强连通分量缩点 )
  • 原文地址:https://www.cnblogs.com/Ateisti/p/6292326.html
Copyright © 2011-2022 走看看