zoukankan      html  css  js  c++  java
  • 【好题】数学+二分+思维——cf1344D/1345F

    /*
    对于每个bi,当bi从x-1提升到x时,对答案的贡献是 ai-3x^2+3x-1, x>=1,函数递减
    即bi越大时,bi+1所获得的增量收益就越低
    
    所以有暴力的解法就是每次找到当前+1后增量最大的那个bi,给其+1 
    
    考虑二分这个增量delta,对每个bi,二分找到x,当bi从x-1增加到x时,获得的增量>=delta
    judge时把所有bi加起来,如果sum<=k,那么delta可以更小,反之delta要更大
    最后的解之和sum可能不到k,那么找这组解中增量最大的k-sum个数+1即可 

    另外记得二分上下界要开的大一点
    */ #include<bits/stdc++.h> using namespace std; #define N 200005 #define ll long long ll sum,n,a[N],k,b[N]; double f(ll a,ll x){ return a-3.0*x*x+3.0*x-1.0; } int judge(ll delta){ sum=0; for(int i=1;i<=n;i++){ ll L=0,R=a[i],mid; b[i]=0; while(L<=R){ mid=L+R>>1; if(f(a[i],mid)>=delta) b[i]=mid,L=mid+1; else R=mid-1; } } for(int i=1;i<=n;i++)sum+=b[i]; if(sum<=k)return 1; return 0; } struct Node{ll id,v,up;}p[N]; int cmp1(Node a,Node b){return a.up>b.up;} int cmp2(Node a,Node b){return a.id<b.id;} int main(){ cin>>n>>k; for(int i=1;i<=n;i++)cin>>a[i]; ll L=-4e18,R=1e18,mid,ans; while(L<=R){ mid=L+R>>1; if(judge(mid))//增量还可以更小 ans=mid,R=mid-1; else L=mid+1; } judge(ans); if(sum==k){ for(int i=1;i<=n;i++)cout<<b[i]<<" "; }else if(sum<k){ for(int i=1;i<=n;i++) p[i].id=i,p[i].v=b[i],p[i].up=f(a[i],b[i]+1); sort(p+1,p+1+n,cmp1); for(int i=1;i<=n;i++)if(p[i].v<a[p[i].id]){ p[i].v++; if(++sum==k)break; } sort(p+1,p+1+n,cmp2); for(int i=1;i<=n;i++)cout<<p[i].v<<' '; } }
  • 相关阅读:
    流式布局思想
    盒子的显隐
    高级布局 浮动 清浮动
    display总结 overflow知识
    边界圆角 盒模型布局 图片背景 精灵图
    io模型
    协程
    GIL 进程池与线程池
    守护进程 互斥锁 进程间通讯
    子进程
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12850647.html
Copyright © 2011-2022 走看看