set+线段树 Codeforces Round #305 (Div. 2) D. Mike and Feet

题目传送门

  1 /*
  2     题意:对于长度为x的子序列,每个序列存放为最小值,输出长度为x的子序列的最大值
  3     set+线段树:线段树每个结点存放长度为rt的最大值,更新:先升序排序,逐个添加到set中
  4                 查找左右相邻的位置,更新长度为r - l - 1的最大值,感觉线段树结构体封装不错!
  5     详细解释:http://blog.csdn.net/u010660276/article/details/46045777
  6     其实还有其他解法,先掌握这种:)
  7 */
  8 #include <cstdio>
  9 #include <algorithm>
 10 #include <iostream>
 11 #include <iostream>
 12 #include <cstring>
 13 #include <set>
 14 using namespace std;
 15 
 16 typedef long long ll;
 17 #define lson l, mid, rt << 1
 18 #define rson mid + 1, r, rt << 1 | 1
 19 
 20 const int MAXN = 2e5 + 10;
 21 const int INF = 0x3f3f3f3f;
 22 
 23 struct A
 24 {
 25     int v, id;
 26     bool operator < (const A &a) const
 27     {
 28         return v < a.v;
 29     }
 30 }a[MAXN];
 31 struct SegmentTree
 32 {
 33     int add[MAXN << 2];
 34     int mx[MAXN << 2];
 35 
 36     void push_down(int rt)
 37     {
 38         if (add[rt])
 39         {
 40             add[rt<<1] = add[rt<<1|1] = add[rt];
 41             mx[rt<<1] = mx[rt<<1|1] = add[rt];
 42             add[rt] = 0;
 43         }
 44     }
 45 
 46     void build(int l, int r, int rt)
 47     {
 48         add[rt] = mx[rt] = 0;
 49         if (l == r)    return ;
 50         int mid = (l + r) >> 1;
 51         build (lson);    build (rson);
 52     }
 53 
 54     void updata(int ql, int qr, int c, int l, int r, int rt)
 55     {
 56         if (ql <= l && r <= qr)    {mx[rt] = c; add[rt] = c;    return ;}
 57         push_down (rt);
 58         int mid = (l + r) >> 1;
 59         if (ql <= mid)    updata (ql, qr, c, lson);
 60         if (qr > mid)    updata (ql, qr, c, rson);
 61     }
 62 
 63     int query(int x, int l, int r, int rt)
 64     {
 65         if (l == r)    return mx[rt];
 66         push_down (rt);
 67         int mid = (l + r) >> 1;
 68         if (x <= mid)    return query (x, lson);
 69         return query (x, rson);
 70     }
 71 }tree;
 72 
 73 int ans[MAXN];
 74 
 75 int main(void)        //Codeforces Round #305 (Div. 2) D. Mike and Feet
 76 {
 77     int n;
 78     while (scanf ("%d", &n) == 1)
 79     {
 80         for (int i=1; i<=n; ++i)
 81         {
 82             scanf ("%d", &a[i].v);    a[i].id = i;
 83         }
 84         sort (a+1, a+1+n);
 85 
 86         tree.build (1, n, 1);
 87         set<int> S;    S.insert (0);    S.insert (n + 1);
 88         set<int>::iterator it;
 89         for (int i=1; i<=n; ++i)
 90         {
 91             int l, r;
 92             it = S.lower_bound (a[i].id);
 93             r = *it; it--; l = *it;
 94             if (r - l - 1 >= 1)    tree.updata (1, r-l-1, a[i].v, 1, n, 1);
 95             S.insert (a[i].id);
 96         }
 97 
 98         for (int i=1; i<=n; ++i)
 99             ans[i] = tree.query (i, 1, n, 1);
100         for (int i=1; i<=n; ++i)
101             printf ("%d%c", ans[i], (i==n) ? '
' : ' ');
102     }
103 
104     return 0;
105 }
106 
107 /*
108 10
109 1 2 3 4 5 4 3 2 1 6
110 */

 

 1 /*
 2     jinye的解法:原理一样,找到最小值是a[i]的最长区间,用l[],r[]记录左右端点的位置
 3                 比线段树快多了:)
 4 */
 5 #include <cstdio>
 6 #include <iostream>
 7 #include <algorithm>
 8 #include <cstring>
 9 #include <cmath>
10 using namespace std;
11 
12 const int MAXN = 2e5 + 10;
13 const int INF = 0x3f3f3f3f;
14 int a[MAXN], l[MAXN], r[MAXN], ans[MAXN];
15 
16 int main(void)        //Codeforces Round #305 (Div. 2) D. Mike and Feet
17 {
18     int n;
19     while (scanf ("%d", &n) == 1)
20     {
21         memset (ans, 0, sizeof (ans));
22         for (int i=1; i<=n; ++i)
23         {
24             scanf ("%d", &a[i]);
25             l[i] = r[i] = i;
26         }
27 
28         for (int i=1; i<=n; ++i)
29         {
30             while (l[i] > 1 && a[i] <= a[l[i]-1])    l[i] = l[l[i]-1];
31         }
32         for (int i=n; i>=1; --i)        //倒过来回超时
33         {
34             while (r[i] < n && a[i] <= a[r[i]+1])    r[i] = r[r[i]+1];
35         }
36 
37         for (int i=1; i<=n; ++i)
38         {
39             int x = r[i] - l[i] + 1;
40             ans[x] = max (ans[x], a[i]);
41         }
42 
43         for (int i=n-1; i>=1; --i)        //可能范围扩展的太厉害了
44         {
45             ans[i] = max (ans[i], ans[i+1]);
46         }
47 
48         for (int i=1; i<=n; ++i)
49             printf ("%d%c", ans[i], (i==n) ? '
' : ' ');
50     }
51 
52     return 0;
53 }
数组效率更高
编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/4534187.html