fzu 1962 树状数组 OR 线段树

时间:2022-09-03 08:51:43

优雅的树状数组!人们发明了复杂度为logn的求解第k小的方法,常数小且代码量小,实在是用来求解本类题目的最佳方法,可惜的是我的Treap超时了......

树状数组:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 
 6 const int N = 500001;
 7 int c[N];
 8 int n, m, maxn;
 9 
10 int lb( int i )
11 {
12     return i & -i;
13 }
14 
15 void update( int i, int v )
16 {
17     while ( i <= n )
18     {
19         c[i] += v;
20         i += lb(i);
21     }
22 }
23 
24 int sum( int i )
25 {
26     int ans = 0;
27     while ( i )
28     {
29         ans += c[i];
30         i -= lb(i);
31     }
32     return ans;
33 }
34 
35 int kth( int k )
36 {
37     int ans = 0, cnt = 0;
38     for ( int i = 20; i >= 0; i-- )
39     {
40         ans += ( 1 << i );
41         if ( ans >= maxn || cnt + c[ans] >= k )
42         {
43             ans -= ( 1 << i );
44         }
45         else
46         {
47             cnt += c[ans];
48         }
49     }
50     return ans + 1;
51 }
52 
53 int main ()
54 {
55     while ( scanf("%d%d", &n, &m) != EOF )
56     {
57         memset( c, 0, sizeof(c) );
58         for ( int i = 1; i <= n; i++ )
59         {
60             update( i, 1 );
61         }
62         maxn = n;
63         while ( m-- )
64         {
65             char op[2];
66             int num;
67             scanf("%s%d", op, &num);
68             if ( op[0] == 'L' )
69             {
70                 int kk = kth(num);
71                 update( kk, -1 );
72             }
73             else if ( op[0] == 'R' )
74             {
75                 if ( sum(num) == sum( num - 1 ) )
76                 {
77                     update( num, 1 );
78                 }
79             }
80             else if ( op[0] == 'Q' )
81             {
82                 int kk = kth(num);
83                 printf("%d\n", kk);
84             }
85         }
86     }
87     return 0;
88 }

线段树当然也可以做:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 
 6 const int N = 500001;
 7 int n, m;
 8 
 9 struct Node 
10 {
11     int l, r, sum;
12 } node[N << 2];
13 
14 void pushup( int i )
15 {
16     node[i].sum = node[i << 1].sum + node[i << 1 | 1].sum;
17 }
18 
19 void build( int i, int l, int r )
20 {
21     node[i].l = l, node[i].r = r, node[i].sum = node[i].r - node[i].l + 1;
22     if ( l == r ) return ;
23     int mid = ( l + r ) >> 1;    
24     build( i << 1, l, mid );
25     build( i << 1 | 1, mid + 1, r );
26 }
27 
28 void update( int i, int pos, int val )
29 {
30     if ( node[i].l == pos && node[i].r == pos )
31     {
32         node[i].sum = val;
33         return ;
34     }
35     int mid = ( node[i].l + node[i].r ) >> 1;
36     if ( pos <= mid )
37     {
38         update( i << 1, pos, val );
39     }
40     else
41     {
42         update( i << 1 | 1, pos, val );
43     }
44     pushup(i);
45 }
46 
47 int query( int i, int v )
48 {
49     if ( node[i].l == node[i].r ) return node[i].l;
50     if ( node[i << 1].sum >= v ) return query( i << 1, v );
51     return query( i << 1 | 1, v - node[i << 1].sum );
52 }
53 
54 int main ()
55 {
56     while ( scanf("%d%d", &n, &m) != EOF )
57     {
58         build( 1, 1, n );
59         scanf("%d", &m);
60         while ( m-- )
61         {
62             char op[2];
63             int x;
64             scanf("%s %d", op, &x);
65             if ( op[0] == 'L' )
66             {
67                 int kk = query( 1, x );
68                 update( 1, kk, 0 );
69             }
70             else if ( op[0] == 'R' )
71             {
72                 update( 1, x, 1 );
73             }
74             else if ( op[0] == 'Q' )
75             {
76                 int kk = query( 1, x );
77                 printf("%d\n", kk);
78             }
79         }
80     }
81     return 0;
82 }