bnuoj 27411 数据结构维护区间RMQ

很显然n方的复杂度过不了。

于是考虑优化最值的查询,可以考虑用堆或者单调队列来做。

堆:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <queue>
 5 using namespace std;
 6 
 7 const int INF = 99999999;
 8 const int N = 32768;
 9 int a[N];
10 int n, l, u;
11 
12 struct Node
13 {
14     int l;
15     int s;
16     Node () {}
17     Node ( int _l, int _s )
18     {
19         l = _l;
20         s = _s;
21     }
22     bool operator < ( const Node & t ) const
23     {
24         return s < t.s;
25     }
26 };
27 
28 int solve()
29 {
30     priority_queue<Node> q;
31     int ans = INF;
32     for ( int i = l; i <= n; i++ )
33     {
34         q.push( Node ( i - l, a[i - l] ) );
35         while ( q.top().l + u < i ) q.pop();
36         int tmp = a[i] - q.top().s;
37         if ( tmp < ans ) ans = tmp;
38     }
39     return ans;
40 }
41 
42 int main()
43 {
44     while ( scanf("%d", &n), n )
45     {
46         scanf("%d%d", &l, &u);
47         a[0] = 0;
48         for ( int i = 1; i <= n; i++ )
49         {
50             scanf("%d", a + i);
51             a[i] += a[i - 1];
52         }
53         printf("%d
", solve());
54     }
55     return 0;
56 }

单调队列:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <queue>
 5 using namespace std;
 6 
 7 const int INF = 99999999;
 8 const int N = 32768;
 9 int a[N];
10 int n, l, u;
11 int head, tail;
12 
13 struct Node
14 {
15     int l, s;
16 } q[N];
17 
18 int solve()
19 {
20     int ans = INF;
21     head = tail = 0;
22     for ( int i = l; i <= n; i++ )
23     {
24         while ( head < tail && a[i - l] > q[tail - 1].s )
25         {
26             tail--;
27         }
28         q[tail].l = i - l, q[tail].s = a[i - l];
29         tail++;
30         while ( q[head].l + u < i ) head++;
31         int tmp = a[i] - q[head].s;
32         if ( tmp < ans ) ans = tmp;
33     }
34     return ans;
35 }
36 
37 int main()
38 {
39     while ( scanf("%d", &n), n )
40     {
41         scanf("%d%d", &l, &u);
42         a[0] = 0;
43         for ( int i = 1; i <= n; i++ )
44         {
45             scanf("%d", a + i);
46             a[i] += a[i - 1];
47         }
48         printf("%d
", solve());
49     }
50     return 0;
51 }

 块状链表:

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <cmath>
  5 using namespace std;
  6 
  7 const int INF = 999999999;
  8 const int N = 32768;
  9 const int M = 500;
 10 int a[N];
 11 int n, tot;
 12 int ps;
 13 int lower, upper;
 14 
 15 int max( int a, int b )
 16 {
 17     return a > b ? a : b;
 18 }
 19 
 20 int min( int a, int b )
 21 {
 22     return a < b ? a : b;
 23 }
 24 
 25 struct Block
 26 {
 27     int num[M];
 28     int size, maxn;
 29     void init()
 30     {
 31         size = 0;
 32         maxn = -INF;
 33     }
 34     void push( int tmp )
 35     {
 36         num[size++] = tmp;
 37         if ( tmp > maxn ) maxn = tmp;
 38     }
 39 } bl[M];
 40 
 41 int query( int l, int r )
 42 {
 43     l++, r++;
 44     int cur = 0, ncur = 0;
 45     while ( l > ps )
 46     {
 47         l -= ps;
 48         cur++;
 49     }
 50     while ( r > ps )
 51     {
 52         r -= ps;
 53         ncur++;
 54     }
 55     int ans = -INF;
 56     for ( int i = cur + 1; i <= ncur - 1; i++ )
 57     {
 58         ans = max( ans, bl[i].maxn );
 59     }
 60     if ( cur == ncur )
 61     {
 62         for ( int j = l - 1; j < r; j++ )
 63         {
 64             ans = max( ans, bl[cur].num[j] );
 65         }
 66     }
 67     else
 68     {
 69         for ( int j = l - 1; j < bl[cur].size; j++ )
 70         {
 71             ans = max( ans, bl[cur].num[j] );
 72         }
 73         for ( int j = 0; j < r; j++ )
 74         {
 75             ans = max( ans, bl[ncur].num[j] );
 76         }
 77     }
 78     return ans;
 79 }
 80 
 81 int main()
 82 {
 83     while ( scanf("%d", &n), n )
 84     {
 85         scanf("%d%d", &lower, &upper);
 86         a[0] = 0;
 87         for ( int i = 1; i <= n; i++ )
 88         {
 89             scanf("%d", a + i);
 90             a[i] += a[i - 1];
 91         }
 92         tot = 0;
 93         bl[tot].init();
 94         ps = sqrt((double)n);
 95         for ( int i = 0; i <= n; i++ )
 96         {
 97             if ( bl[tot].size == ps )
 98             {
 99                 tot++;
100                 bl[tot].init();
101             }
102             bl[tot].push(a[i]);
103         }
104         int ans = INF;
105         for ( int i = lower; i <= n; i++ )
106         {
107             int qq = query( max( i - upper, 0 ), i - lower );
108             ans = min( ans, a[i] - qq );
109         }
110         printf("%d
", ans);
111     }
112     return 0;
113 }

还可以用线段树或者RMQ的ST算法,解法实在是太多了。

原文地址:https://www.cnblogs.com/huoxiayu/p/4470981.html