Topic link: https: //ac.nowcoder.com/acm/contest/889/H
The meaning of problems: given height, q n pieces of bamboo sub-query, query given every l, r, x, y, each select [l, r] in bamboo, bamboo cut all cut of y, each cut down bamboo and length are the same, ask your x-th which should cut down on height
Problem-solving ideas: As the total number of cut has been given, so we can know the chop chop x times the amount of total Total = $\sum\limits_{i=l}^{r}$
h[i]*x/y
,那么问题就变成了一个方程$\sum\limits_{i=l}^{r}$
,我们需要求的就是ansmax(0,h[i]-ans)=Total
That is greater than the number obtained in the range of minus ans ans is equal to Total, using the Chairman of the tree we can find a range larger than the number num and their number and sum, then we only need half ans verification can be. The time complexity of O ($nlog^{2}n$),后来我了解到一种更好的做法,
We need to access some interval greater than ans is to calculate the answer, we recursively processing this interval [L, R], first calculated in the right interval [M + 1, R] values into the equation, then the value interval M (Why selected from the group M, as explained later) as the assumptions ans, then we can obtain a value of tmp, so val = Total
1, if tmp <Total, ans illustrate this election is too great, we need a smaller ans, therefore recursive processing of the current interval [L, M] to find a more suitable ans, then we need to make recursive val - = tmp, that is to say, we only need to pass the current offset value into account, to the left in the recursive interval [L, M], we continue to select the value interval ML hypotheses as ANS, then we need to recalculate tmp value, however, the current Total has a problem (it is a hypothesis ans = M calculated on based on), in order to correct Total, we just lost once in the calculation tmp added before the first num M (which is the current left range R, which is why select M as the reason for the assumption ans is, we can get the last hypothesis ans), then the current assumptions ans = ML recalculate the tmp value, note that we have to maintain a current has been selected the number of bamboo NUM , so that we can compute tmp, tmp after calculate the value, you can recursively
2, if tmp> Total, illustrate the ans selected too small, we need to go to the right interval [M + 1, R] is assumed to find a suitable back ans, so we maintain parameters constant interval to the right recursively
When we reach the end of recursion, L == R, described, if we assume the value of R is selected there is still a deviation val (val may be zero, but it does not matter), L-1 is selected will cause$\sum\limits_{i=l}^{r}$
,max(0,h[i]-ans)>Total
因此我们可以根据这个偏差值val去修正假设的ans=L去得到真正的答案,真正的ans=L-val/(以及选取的所有竹子个数+高为L的竹子个数(以L为假设ans时,我们认为高为L的竹子是没有被砍的))时间复杂度O(nlogn)
AC Code:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 2e5+5; #define eps 1e-8 struct Node { int l,r,num; ll sum; }node[maxn*20]; int h[maxn],root[maxn],tot; ll preSum[maxn]; void update(int &x,int y,int l,int r,int val) { x=++tot; node[x]=node[y]; ++node[x].num; node[x].sum+=val; if(l==r)return; int m=(l+r)>>1; if(val<=m)update(node[x].l,node[y].l,l,m,val); else update(node[x].r,node[y].r,m+1,r,val); } double query(int x,int y,int L,int R,double val,ll num) { if(L==R)return L-val/(node[x].num-node[y].num+num); int m=(L+R)>>1; ll cnt=node[node[x].r].num-node[node[y].r].num; ll tmp=node[node[x].r].sum-node[node[y].r].sum-cnt*m+num*(R-m); if(tmp+eps<val)return query(node[x].l,node[y].l,L,m,val-tmp,num+cnt); return query(node[x].r,node[y].r,m+1,R,val,num); } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, q; cin >> n >> q; for (int i = 1; i <= n; i++) { cin >> h[i]; preSum[i] = preSum[i - 1] + h[i]; update(root[i], root[i - 1], 1, 1e5, h[i]); } while (q--) { int l, r, x, y; cin >> l >> r >> x >> y; printf("%.12f\n", query(root[r], root[l - 1], 1, 1e5, 1.0 * (preSum[r] - preSum[l - 1]) / Y * x, 0 )); } Return 0 ; }