1 /* 2 题意:对于长度为x的子序列,每个序列存放为最小值,输出长度为x的子序列的最大值 3 set+线段树:线段树每个结点存放长度为rt的最大值,更新:先升序排序,逐个添加到set中 4 查找左右相邻的位置,更新长度为r - l - 1的最大值,感觉线段树结构体封装不错! 5 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) ? '\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) ? '\n' : ' '); 50 } 51 52 return 0; 53 }