标签:codeforces 数据结构
题意:
n(10^5)个模板形成的栅栏 q(10^5)个询问 每个询问要求在[u,v]木板区间内摆放一个宽度为w的矩形 问矩形最大的高是多少
思路:
对于每个询问 可以通过logn的二分来将求解最大h的问题转化为当前h‘情况下的判定问题
为什么可以二分呢 因为如果我们将木板排序 从大到小的依次放置它们的位置上 那么对于某一时刻 线段上连续的1就代表了矩形的宽 同时这时的h最小为二分到的木板高度h’ 明显h‘和这时矩形的宽满足单调性
得到了h’后只需要快速的找出[u,v]区间连续的1的长度是否超过w就好了 这就需要我们提供一种能“追溯到过去任何时刻”的数据结构 而且这个数据结构能在log时间内回答上述问题 明显可持久化线段树满足要求
那么我们可以nlogn的建树 然后二分h 再通过可持久化线段树询问区间内最长的连续的1长度是否超过w 这样对于询问的处理就是m(logn)^2的了
代码:
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<map> #include<set> #include<vector> #include<queue> #include<cstdlib> #include<ctime> #include<cmath> #include<bitset> using namespace std; typedef long long LL; #define N 100010 #define TS 2000010 #define L(x) (ch[x][0]) #define R(x) (ch[x][1]) int n, q; struct fzc { int h, id; bool operator<(const fzc ff) const { return h > ff.h; } } f[N]; int ch[TS][2], T[TS], fleft[TS], fright[TS], maxsum[TS], tot; int build(int l, int r) { int i = tot++; fleft[i] = fright[i] = maxsum[i] = 0; if (l != r) { int mid = (l + r) >> 1; L(i) = build(l, mid); R(i) = build(mid + 1, r); } return i; } void up(int i, int l, int r) { int mid = (l + r) / 2; fleft[i] = fleft[L(i)]; if (fleft[L(i)] == mid - l + 1) fleft[i] += fleft[R(i)]; fright[i] = fright[R(i)]; if (fright[R(i)] == r - mid) fright[i] += fright[L(i)]; maxsum[i] = max(fright[L(i)] + fleft[R(i)], max(maxsum[L(i)], maxsum[R(i)])); } int insert(int old, int pos, int l, int r) { int i = tot++; L(i) = L(old); R(i) = R(old); if (pos == l && pos == r) { fleft[i] = fright[i] = maxsum[i] = 1; return i; } int mid = (l + r) / 2; if (pos <= mid) L(i) = insert(L(old), pos, l, mid); else R(i) = insert(R(old), pos, mid + 1, r); up(i, l, r); return i; } int toleft, res; void query(int i, int l, int r, int fl, int fr) { if (l == fl && r == fr) { res = max(res, maxsum[i]); toleft += fleft[i]; res = max(res, toleft); if (fleft[i] != fr - fl + 1) toleft = fright[i]; res = max(res, toleft); return; } int mid = (fl + fr) / 2; if (r <= mid) query(L(i), l, r, fl, mid); else if (l > mid) query(R(i), l, r, mid + 1, fr); else { query(L(i), l, mid, fl, mid); query(R(i), mid + 1, r, mid + 1, fr); } } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &f[i].h); f[i].id = i; } sort(f + 1, f + n + 1); tot = 1; T[0] = build(1, n); for (int i = 1; i <= n; i++) T[i] = insert(T[i - 1], f[i].id, 1, n); scanf("%d", &q); while (q--) { int u, v, w; scanf("%d%d%d", &u, &v, &w); int l = 1, r = n, mid, ans; while (l <= r) { mid = (l + r) / 2; toleft = res = 0; query(T[mid], u, v, 1, n); if (res >= w) { ans = mid; r = mid - 1; } else l = mid + 1; } printf("%d\n", f[ans].h); } return 0; }
标签:codeforces 数据结构
原文地址:http://blog.csdn.net/houserabbit/article/details/41704311