codeforces 484E
题意:给定n<=105的数组h,有m<=105的询问,每个询问为l,r,w求[l,r]区间内连续w个的最小高度最大是多少..
思路:首先把h数组从大到小排序,然后用建立一个可持久化的下标线段树,线段树维护区间最长的连续长度为多少。
那么对于每个询问直接二分高度,然后查询这个高度之前的线段树[l,r]区间是否存在至少w个连续的。。
以前总是套主席树模板,这次自己写感觉也还是蛮好写的。。
据说cdq分治也可搞。。应该是整体二分吧。。明天再想想
code:
1 /* 2 * Author: Yzcstc 3 * Created Time: 2014/11/10 22:17:29 4 * File Name: cf276E.cpp 5 */ 6 #include<cstdio> 7 #include<iostream> 8 #include<cstring> 9 #include<cstdlib> 10 #include<cmath> 11 #include<algorithm> 12 #include<string> 13 #include<map> 14 #include<set> 15 #include<vector> 16 #include<queue> 17 #include<stack> 18 #include<ctime> 19 #define M0(a) memset(a, 0, sizeof(a)) 20 #define N 101010 21 #define M 3100000 22 #define x first 23 #define y second 24 #define ls lson[rt] 25 #define rs rson[rt] 26 using namespace std; 27 typedef pair<int, int> pii; 28 struct node{ 29 int c, lc, rc; 30 node(int _c = 0, int _lc = 0, int _rc = 0):c(_c), lc(_lc), rc(_rc){} 31 }; 32 pair<int, int> p[N]; 33 int T[N], lc[M], rc[M], c[M], lson[M], rson[M], tot; 34 int n, m; 35 36 int build(const int l, const int r){ 37 int root = tot++; 38 c[root] = lc[root] = rc[root] = 0; 39 if (l < r){ 40 int mid = (l + r) >> 1; 41 lson[root] = build(l, mid); 42 rson[root] = build(mid+1, r); 43 } 44 return root; 45 } 46 47 void push_up(const int& rt, const int& llen, const int &rlen){ 48 lc[rt] = (c[ls] >= llen) ? llen + lc[rs] : lc[ls]; 49 rc[rt] = (c[rs] >= rlen) ? rlen + rc[ls] : rc[rs]; 50 c[rt] = max(c[ls], c[rs]), c[rt] = max(lc[rs] + rc[ls], c[rt]); 51 } 52 53 int update(const int rt, const int l, const int r, const int& p){ 54 int root = tot++; 55 if (p <= l && r <= p){ 56 c[root] = rc[root] = lc[root] = 1; 57 return root; 58 } 59 int mid = (l + r) >> 1; 60 lson[root] = ls, rson[root] = rs; 61 if (p <= mid) 62 lson[root] = update(ls, l, mid, p); 63 else 64 rson[root] = update(rs, mid+1, r, p); 65 push_up(root, mid-l+1, r-mid); 66 return root; 67 } 68 69 node tmp, t; 70 void merge(node &a, const node& b,const int& llen,const int& rlen){ 71 t.c = max(a.c, b.c), t.c = max(t.c, a.rc + b.lc); 72 t.lc = (a.lc >= llen) ? a.lc + b.lc : a.lc; 73 t.rc = (b.rc >= rlen) ? b.rc + a.rc : b.rc; 74 a = t; 75 } 76 77 node query(const int& rt,const int& l,const int& r,const int& L,const int& R){ 78 if (L <= l && r <= R) return node(c[rt], lc[rt], rc[rt]); 79 int mid = (l + r) >> 1; 80 if (R <= mid) return query(ls, l, mid, L, R); 81 else if (L > mid) return query(rs, mid + 1, r, L, R); 82 else{ 83 node res = query(ls, l, mid, L, R); 84 tmp = query(rs, mid+1, r, L, R); 85 merge(res, tmp, mid - max(L, l) + 1, min(R,r) - mid); 86 return res; 87 } 88 } 89 90 void init(){ 91 scanf("%d", &n); 92 tot = 0; 93 for (int i = 1; i <= n; ++i) 94 scanf("%d", &p[i].x), p[i].y = i; 95 sort(p + 1, p + 1 + n, greater<pii>() ); 96 } 97 98 void solve(){ 99 T[0] = build(1, n); 100 for (int i = 1; i <= n; ++i) 101 T[i] = update(T[i-1], 1, n, p[i].y); 102 int q, ll, rr, w, l, r, mid, ans; 103 scanf("%d", &q); 104 while (q--){ 105 scanf("%d%d%d", &ll, &rr, &w); 106 l = 1, r = n, ans = 0; 107 while (l <= r){ 108 mid = (l + r) >> 1; 109 if (query(T[mid], 1, n, ll, rr).c >= w){ 110 ans = max(ans, p[mid].x); 111 r = mid - 1; 112 } else l = mid + 1; 113 } 114 printf("%d\n", ans); 115 } 116 117 } 118 119 120 int main(){ 121 init(); 122 solve(); 123 return 0; 124 }