您的位置:首页 > Web前端

可持久化线段树 CF484E-Sign on Fence

2014-11-09 10:38 267 查看
题目链接

题目大意:1-n每个位置上有一个固定高度的建筑物,有若干次询问,每次询问 [l, r] 区间内,连续横跨长度为w,高度最矮的建筑物最高为多少。

解题思路:可持久化线段树,按高度为建树,每次询问为针对一段区间,最长的连续和为多少。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <cassert>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#define RD(x) scanf("%d", &x)
#define REP(i, n) for (int i=0; i<int(n); i++)
#define FOR(i, n) for (int i=1; i<=int(n); i++)
#define pii pair<int, int>
#define mp make_pair
#define pb push_back
inline int read(){int ret; scanf("%d", &ret); return ret;}
//int dx[8] = {1, 1, 0, -1, -1, -1, 0, 1};
//int dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

using namespace std;
#define N 123456
#define M 22222
#define eps 1e-8
#define pi acos(-1.0)
#define inf 0X5FFFFFFFFFFFFFFFll
#define mod 1000000007ll
#define LL long long
#define ULL unsigned long long
struct Seg {
Seg *l, *r;
int ll, rr, len, d;
void pushUp() {
len = max((l?l->rr:0) + (r?r->ll:0),
max(l?l->len:0, r?r->len:0));
ll = l?l->ll:0;
if (l && r && l->len == l->d)
ll = l->d + r->ll;
rr = r?r->rr:0;
if (l && r && r->len == r->d)
rr = r->d + l->rr;
}
}pool[N*20], *cur = pool;

Seg *root
;

Seg *newNode(int l, int r) {
cur->l = cur->r = NULL;
cur->ll = cur->rr = cur->len = 0;
cur->d = r - l + 1;
return cur++;
}

Seg *update(int x, int l, int r, Seg *now) {
Seg *ret = newNode(l, r);
if (now != NULL)
*ret = *now;
if (l == r) {
ret->ll = ret->rr = ret->len = 1;
return ret;
}
int mid = (l + r) >> 1;
if (x <= mid)
ret->l = update(x, l, mid, now?now->l:NULL);
if (x > mid)
ret->r = update(x, mid+1, r, now?now->r:NULL);
ret->pushUp();
return ret;
}

Seg *p0
;
int tot;
void _query(int l, int r, int L, int R, Seg *now) {
if (l <= L && R <= r) {
p0[tot++] = now;
return;
}
int mid = (L + R) >> 1;
if (l <= mid)
_query(l, r, L, mid, now?now->l:NULL);
if (r > mid)
_query(l, r, mid+1, R, now?now->r:NULL);
}

int query(int l, int r, int L, int R, Seg *now) {
tot = 0;
_query(l, r, L, R, now);
int pre = 0;
int ret = 0;
REP(i, tot) {
pre += p0[i]?p0[i]->ll:-pre;
ret = max(ret, max(pre, p0[i]?p0[i]->len:0));
pre = p0[i]?(p0[i]->len == p0[i]->d? pre:p0[i]->rr):0;
}
return ret;
}

pii h
;
int height
;

int Main() {
//freopen("cf.txt", "r", stdin);
ios_base::sync_with_stdio(0);
int n, m;
cin >> n;
FOR(i, n) {
cin >> h[i].first;
h[i].second = i;
}
sort(h + 1, h + n + 1, [](const pii &a, const pii &b) {return a.first > b.first;});

FOR(i, n)
root[i] = update(h[i].second, 1, n, root[i-1]);

cin >> m;
while (m--) {
int L, R, W;
cin >> L >> R >> W;
int l = 1, r = n;
while (l < r) {
int mid = (l + r) >> 1;
if (query(L, R, 1, n, root[mid]) >= W)
r = mid;
else
l = mid + 1;
}
cout << h[l].first << endl;
}

return 0;
}

int main() {
return Main();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 algorithm