链接:https://ac.nowcoder.com/acm/contest/889/H
来源:牛客网
There are n bamboos arranged in a line. The i-th bamboo from the left has height hih_{i}hi.
You are given q queries of the type (l, r, x, y). For each query (l, r, x, y) we consider only the l-th to r-th bamboo inclusive. We want to make y horizontal cuts through these bamboos, such that after each cut, the total length of bamboo cut is the same, and after all y cuts there is no bamboo left. For example, if there are 3 bamboos of height 3, 4, 5 respectively and y = 4. The first cut should be at height 3, after which the heights of the bamboos are 3, 3, 3 respectively and the total amount of bamboo cut is 0 + 1 + 2 = 3. Then, the next 3 cuts should be at height 2, 1, 0 respectively. You want to find out what is the height the x-th cut is performed.
Note that after each query, the bamboos are not actually cut, so the heights of the bamboos remain constant after each query.
The first line of input contains two space-separated integers n, q (1 <= n <= 200000, 1 <= q <= 100000). The next line of input contains n space-separated integers, the i-th of which denotes hi, the height of the i-th bamboo (1 <= hi <= 100000). The next q lines of input contains 4 space-separated integers each, denoting l, r, x, y (1 <= l <= r <= n, 1 <= x <= y <= 109).
Output q lines of real numbers, the i-th line contains the answer to the i-th query. Your answer will be accepted if its absolute or relative error is less than 10-6.
示例1
复制
5 4 3 5 1 7 4 2 4 3 5 1 4 4 9 1 3 1999 101111 2 2 1 1
复制
2.100000005215406 2.629629638046026 4.822066854685545 0.000000026077032
For the first query, we only consider the bamboos of height 5, 1, 7. The first cut should be at height 4.7, the total amount of bamboo obtained is 0.3 + 0 + 2.3 = 2.6. The second cut should be at height 3.4, the total amount of bamboo obtained is 1.3 + 0 + 1.3 = 2.6. The third cut should be at height 2.1, the total amount of bamboo obtained is 1.3 + 0 + 1.3 = 2.6. The fourth cut should be at height 13/15, the total amount of bamboo obtained is 37/30 + 2/15 + 37/30 = 2.6. The fifth cut should be at height 0, the total amount of bamboo obtained is 13/15 + 13/15 + 13/15 = 2.6. Note that the output values are not exact, but are within the precision requirements.
首先建立主席树,维护区间内不同长度间的num和sum。
假设砍到长度k,那么总的保留下来长度有所有小于等于K的和加上,大于K的长度的竹子数量*K这个高度。
然后进行二分枚举K,注意一下eps即可。
再不了解的加主页Q或留言即可
#include
using namespace std;
const int maxn = 200005;
const int N = 200003;
const int M = maxn * 30;
int n, q, tot; long long sum, num;
int T[maxn], lson[M], rson[M]; long long c[M], nu[M], su[maxn];
int build(int l, int r) {
int root = tot++;
c[root] = 0;
nu[M] = 0;
if (l != r) {
int mid = (l + r) >> 1;
lson[root] = build(l, mid);
rson[root] = build(mid + 1, r);
}
return root;
}
int update(int root, int pos, int val) {
int newroot = tot++, tmp = newroot;
c[newroot] = c[root] + val; nu[newroot] = nu[root] + 1;
int l = 1, r = N;
while (l < r) {
int mid = (l + r) >> 1;
if (pos <= mid) {
lson[newroot] = tot++; rson[newroot] = rson[root];
newroot = lson[newroot]; root = lson[root];
r = mid;
}
else {
rson[newroot] = tot++; lson[newroot] = lson[root];
newroot = rson[newroot]; root = rson[root];
l = mid + 1;
}
c[newroot] = c[root] + val;
nu[newroot] = nu[root] + 1;
}
return tmp;
}
void query(int left_root, int right_root, int l, int r, int k) {
if (l > k)return;
if (r <= k) {
sum += c[right_root] - c[left_root];
num += nu[right_root] - nu[left_root];
return;
}
int mid = (l + r) >> 1;
query(lson[left_root], lson[right_root], l, mid, k);
query(rson[left_root], rson[right_root], mid + 1, r, k);
}
int main() {
scanf("%d%d", &n, &q); tot = 0;
T[0] = build(1, N);
for (int i = 1; i <= n; i++) {
int hi; scanf("%d", &hi);
su[i] = su[i - 1] + hi;
T[i] = update(T[i - 1], hi, hi);
}
while (q--) {
int l, r, x, y;
scanf("%d%d%d%d", &l, &r, &x, &y);
double li = 0, ri = 100000.0, eps = 1e-10;
while (abs(li - ri) > eps) {
double mid = (li + ri) / 2;
sum = 0; num = 0;
query(T[l - 1], T[r], 1, N, (int)mid);
num = (r - l + 1) - num;
double s = mid * num + sum;
double step = 1.0*(su[r] - su[l - 1]) / y;
if (step * (y - x) < s)ri = mid;
else li = mid;
}
printf("%.15lf\n", li);
}
return 0;
}