【题解】P12914 [POI 2020/2021 R2] 沙滩游客 / Plażowicze
题意
给定一个有
- 令
p 为满足x_{i+1}-x_i 最大的i 中的最小值,在x_p 和x_{p+1} 中插入\displaystyle\frac{x_p+x_{p+1}}{2} 。
求第
思路
每次操作可以理解为把长度最大的区间劈成两半,考虑朴素做法,设一个大根堆,记
然后我们可以按
由于
由于每轮操作最多
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
struct fact{int x,y;};
bool operator<(const fact x,const fact y){return x.x*y.y<y.x*x.y;}
bool operator>(const fact x,const fact y){return x.x*y.y>y.x*x.y;}
bool operator==(const fact x,const fact y){return x.x*y.y==y.x*x.y;}
bool operator!=(const fact x,const fact y){return x.x*y.y!=y.x*x.y;}
struct data1{int k,id;}ask[N];
bool cmp(data1 x,data1 y){return x.k<y.k;}
struct data2
{
int pos,cnt;
fact len;
};
bool operator<(const data2 x,const data2 y){return(x.len!=y.len?x.len<y.len:x.pos>y.pos);}
bool operator>(const data2 x,const data2 y){return(x.len!=y.len?x.len>y.len:x.pos<y.pos);}
int a[N];
fact ans[N];
void solve()
{
int n,len,q;
cin>>n>>len>>q;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=q;i++)cin>>ask[i].k,ask[i].id=i;
sort(ask+1,ask+q+1,cmp);
priority_queue<data2>heap;
for(int i=2;i<=n;i++)heap.push({a[i-1],1,{a[i]-a[i-1],1}});
int sum=0;
for(int i=1;;)
{
auto now=heap.top();
heap.pop();
fact tmp=now.len;
if((tmp.x&1)^1)tmp.x>>=1;
else tmp.y<<=1;
while(i<=q&&sum+now.cnt>=ask[i].k)
{
int id=ask[i].id;
ans[id]={now.pos*now.len.y+now.len.x*(ask[i].k-sum-1),now.len.y};
if(now.len.y!=tmp.y)ans[id].x<<=1,ans[id].y<<=1;
ans[id].x+=tmp.x,i++;
}
if(i>q)break;
heap.push({now.pos,now.cnt<<1,tmp});
sum+=now.cnt;
}
for(int i=1;i<=q;i++)
{
int gcd=__gcd(ans[i].x,ans[i].y);
cout<<ans[i].x/gcd<<'/'<<ans[i].y/gcd<<'\n';
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int _=1;
for(;_;_--)solve();
return 0;
}