日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【CF1344D】Résumé Review【数学】【二分】

發布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【CF1344D】Résumé Review【数学】【二分】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意:給定長度為nnn的自然數序列aaa和整數kkk,要求構造長度為nnn的自然數序列bbb,使得0≤bi≤ai,∑bi=k0\leq b_i\leq a_i,\sum b_i=k0bi?ai?,bi?=k,且∑bi(ai?bi2)\sum b_i(a_i-b_i^2)bi?(ai??bi2?)最大化。

n≤105n\leq 10^5n105

要求最大化的是b(a?b2)b(a-b^2)b(a?b2),記為f(x)=x(a?x2)f(x)=x(a-x^2)f(x)=x(a?x2)

注意到xxx每增加111f(x)f(x)f(x)會增加Δi(x)=ai?3x2?3x?1\Delta_i(x)= a_i-3x^2-3x-1Δi?(x)=ai??3x2?3x?1

注意到對于每個iii,當x≥0x\geq 0x0時,Δi(x)\Delta_i(x)Δi?(x)單調遞減,題目所求就是所有數中的前kkk大之和,而每個Δi\Delta_iΔi?被取的一定是前面若干個,所以可以套路性地維護當前的xix_ixi?和一個堆,每次取堆頂讓對應的xi+1x_i+1xi?+1

這樣復雜度是O(klog?n)O(k\log n)O(klogn)無法通過

但是每次加上的Δi(x)\Delta_i(x)Δi?(x)是單調遞減的(廢話),所以可以二分最小的d=Δi(x)d=\Delta_i(x)d=Δi?(x),再二分出每個Δi\Delta_iΔi?被選了多少個,判斷∑xi<k\sum x_i<kxi?<k

最后∑xi\sum x_ixi?可能小于kkk,但每個位置最多只能+1+1+1,直接在當前基礎上暴力選k?∑xik-\sum x_ik?xi?

復雜度O(nlog?2V)O(n\log^2V)O(nlog2V)

#include <iostream> #include <cctype> #include <cstring> #include <cstdio> #include <algorithm> #define MAXN 100005 using namespace std; typedef long long ll; const ll INF=4e18; int a[MAXN],b[MAXN],x[MAXN],p[MAXN],n; ll k,sum; inline ll delta(const int& a,const int& x){return x==a? -INF:a-3ll*x*x-3ll*x-1;} inline bool cmp(int A,int B){return delta(a[A],x[A])>delta(a[B],x[B]);} inline bool check(ll v) {for (int i=1;i<=n;i++){if (delta(a[i],0)<v) x[i]=0;else{int l=0,r=a[i]-1,mid;while (l<r){mid=(l+r+1)>>1;if (delta(a[i],mid)<v) r=mid-1;else l=mid;}x[i]=l+1;}}sum=0;for (int i=1;i<=n;i++) sum+=x[i];if (sum>k) return false;for (int i=1;i<=n;i++) b[i]=x[i];return true; } int main() {cin>>n>>k;for (int i=1;i<=n;i++) scanf("%d",&a[i]);ll l=-INF,r=INF,mid,ans;while (l<r){mid=(l+r)/2;if (check(mid)) ans=mid,r=mid-1;else l=mid+1;}check(ans);for (int i=1;i<=n;i++) p[i]=i;sort(p+1,p+n+1,cmp);for (int i=1;i<=k-sum;i++) ++b[p[i]];for (int i=1;i<=n;i++) printf("%d ",b[i]);return 0; }

總結

以上是生活随笔為你收集整理的【CF1344D】Résumé Review【数学】【二分】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。