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\n", 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\n", 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\n", ans);

111     }

112     return 0;

113 }

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

你可能感兴趣的:(数据结构)