链接: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 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.
题意: 给你一排竹子,每次砍一个区间的竹子,将该区间在恰好砍y次以后竹子高度为0,要求每次砍掉的竹子总长度相等,问第x次砍的竹子高度是多少?
每一次询问过后,竹子都会恢复原来的高度
思路: 我们可以计算得出到第x次时,总共砍下的总长度,所以我们可以二分高度,用主席树得到在区间范围内,低于二分高度的竹子长度与数量,从而确定第x次砍竹子的高度
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
const int M=1e5;
const double eps=1e-8;
int rt[N],ls[N*32],rs[N*32],sum[N*32];
int cnt;
ll s[N],val[N*32];
void update(int &now,int pre,int l,int r,int k)
{
now=++cnt;
sum[now]=sum[pre]+1;
val[now]=val[pre]+k;
ls[now]=ls[pre];
rs[now]=rs[pre];
if(l==r)
return ;
int mid=(l+r)>>1;
if(k<=mid)
update(ls[now],ls[pre],l,mid,k);
else
update(rs[now],rs[pre],mid+1,r,k);
}
ll h,sh;
void query(int now,int pre,int l,int r,int x)
{
if(l>x)
return ;
if(r<=x)
{
sh+=val[now]-val[pre];
h+=sum[now]-sum[pre];
return ;
}
int mid=(l+r)>>1;
query(ls[now],ls[pre],l,mid,x);
query(rs[now],rs[pre],mid+1,r,x);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
s[i]=s[i-1]+x;
update(rt[i],rt[i-1],1,M,x);
}
while(m--)
{
int l,r,x,y;
scanf("%d%d%d%d",&l,&r,&x,&y);
double l1=0,r1=100000.0;
while(r1-l1>eps)
{
h=sh=0;
double mid=(l1+r1)/2;
query(rt[r],rt[l-1],1,M,(int)mid);
h=(r-l+1)-h;
double tmp=mid*h+sh;
if(tmp-(s[r]-s[l-1])*1.0/y*(y-x)>eps)
r1=mid;
else
l1=mid;
}
printf("%.6f\n",l1);
}
return 0;
}