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 }
View Code

 

posted on 2014-11-11 00:12  yzcstc  阅读(355)  评论(0编辑  收藏  举报