[TK] 送礼物
1.[TK] 矩阵取数游戏<简单版> hzoi-tg-906-22.[TK] 一心净士 hzoj-tg-937-23.[TK] 盖房子 hzoi-tg#2624.[TK] 三角蛋糕 hzoi-tg#2615.[TK] 选课 hzoj-tg#2796.[TK] 三色二叉树 hzoi-tg#282 存图方法7.[TK] HH的项链 离线树状数组解法8.[TK] 理想的正方形9.[TK] Blocks 单调栈
10.[TK] 送礼物
11.[TK] Terrible Prime12.[TK] BLO13.[TK] Rudolf and Subway ( CodeForces #933 div.3 - G )14.[TK] Bulls And Cows S15.[TK] 颜色16.[Tkey] 与非17.[TK] CF1526B I Hate 111118.[TK] 寻宝游戏19.[CL-22] 异或和之和20.联训题单 / 集训杂题纪要21.[At_dp_w] Intervals & [At_dp_x] Tower22.CF2023D - Many Games23.[NOI2021] 轻重边24.[CSP-S 2024] 染色题解引用
引理1: 区间
是最优解的必要不充分条件是: 分别是区间的最小值与最大值.
这很显然,若假设不成立,当区间向内缩小时,一定有分子不变,分母变小,进而算出更优解,与假设矛盾.
引理2: 最优解不小于
的充要条件为存在区间 ,使得 或 .
证明一下引理2:
题设转化为公式表达为:
移项:
假设我们已经通过引理1,使区间可能成为最优解,那么公式可以变为:
略微整理一下即为上述引理内容.
题目分析
根据题解可以看出来,我们一共有两个引理需要维护.
注意到引理1我们可以通过以下方式使用单调队列快速维护:
- 遍历不是以端点为阶段,而是以长度为阶段. 即当
时,固定左端点,使其始终为单调队列最小值,伸长右端点,不断更新最值,这样即可一次遍历找出所有符合引理1的区间. 另一种情况同理.
注意到题中
- 二分枚举一个答案值
. - 根据引理2,我们分别维护
与 的单调的队列,方便进行值 的可行性判断. - 根据引理1,我们通过上述方法找出全部可能为最优解的区间.
- 根据引理2,只要有一个区间满足条件,那么值
即为可行的. - 重复上述步骤。直到精度满足要求.
代码实现
double a[5000001],c[5000001];
int main(){
int t;
cin>>t;
while(t--){
int n,k,L,R;
cin>>n>>k>>L>>R;
for(int i=1;i<=n;++i){
cin>>a[i];
}
double l=0,r=1000;
while(r-l>1e-7){ //1e-7比较玄学,开小了容易超时,开大了达不到精度,还会莫名tle
double mid=(l+r)/2; //使用循环版本的二分答案
bool flag=false;
deque<int> q;
for(int i=1;i<=n;++i){ //check部分开始
c[i]=a[i]-1.0*mid*i; //维护a[i]-x*i
}
for(int i=L;i<=n;++i){ //枚举区间长度
while(!q.empty()&&i-q.front()>=R){
q.pop_front();
} //维护最值
while(!q.empty()&&c[q.back()]>=c[i-L+1]){
q.pop_back();
}
q.push_back(i-L+1);
if(c[i]-c[q.front()]>=mid*k){
l=mid;
flag=true; //假如有一个满足的,check成功
break;
}
}
if(!flag){ //再写一遍另一种情况
q.clear();
for(int i=1;i<=n;++i){
c[i]=a[i]+1.0*mid*i; //维护a[i]+x*i
}
for(int i=L;i<=n;++i){
while(!q.empty()&&i-q.front()>=R){
q.pop_front();
}
while(!q.empty()&&c[q.back()]<=c[i-L+1]){
q.pop_back();
}
q.push_back(i-L+1);
if(c[q.front()]-c[i]>=mid*k){
l=mid;
flag=true;
break;//check部分结束
}
}
if(!flag){
r=mid;//二分结束
}
}
}
double ans=l; //根据答案算答案,写的比较不好,就当个参考
deque<int> q1,q2;
for(int i=1;i<=L-1;++i){
while(!q1.empty()&&a[q1.back()]<=a[i]){
q1.pop_back();
}
while(!q2.empty()&&a[q2.back()]>=a[i]){
q2.pop_back();
}
q1.push_back(i);
q2.push_back(i);
}
for(int i=L;i<=n;++i){
while(!q1.empty()&&a[q1.back()]<=a[i]){
q1.pop_back();
}
while(!q2.empty()&&a[q2.back()]>=a[i]){
q2.pop_back();
}
q1.push_back(i);
q2.push_back(i);
while(!q1.empty()&&i-q1.front()>=L){
q1.pop_front();
}
while(!q2.empty()&&i-q2.front()>=L){
q2.pop_front();
}
if(!q1.empty()&&!q2.empty()){
ans=max(ans,1.0*(a[q1.front()]-a[q2.front()])/(L+k-1));
}
}
printf("%.4f\n",ans);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!