可持久化线段树 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();
}
题目大意: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();
}
相关文章推荐
- [CF484E]Sign on Fence
- 【CF484E】Sign on Fence(主席树)
- 【CF484E】Sign on Fence(主席树)
- [CF484E]Sign on Fence
- 【bzoj 2588】Count on a tree(可持久化线段树+LCA)
- SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)
- 2588: Spoj 10628. Count on a tree[可持久化线段树+倍增lca]
- AC日记——Sign on Fence Codeforces 484e
- [BZOJ2588]Count on a tree(可持久化权值线段树|主席树)
- 【spoj】【COT - Count on a tree】【可持久化线段树】
- Codeforces Round #276 (Div. 1) E. Sign on Fence 二分+主席树
- 【可持久化线段树】[SPOJ COT]Count on a tree
- bzoj2588:Count on a tree(可持久化线段树+Lca)
- CF&&CC百套计划4 Codeforces Round #276 (Div. 1) E. Sign on Fence
- CF 484E - Sign on Fence
- 2588: Spoj 10628. Count on a tree (可持久化线段树)
- 【BZOJ2588】【Spoj 10628.】 Count on a tree 可持久化线段树+lca
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
- Single Sign On
- ASP.NET 2.0: Implementing Single Sign On (SSO) with Membership API