首页 > 其他 > 详细

牛客网2018暑期ACM多校训练营(第二场)G transform 尺取法 带权中位数

时间:2018-11-01 21:24:01      阅读:158      评论:0      收藏:0      [点我收藏+]
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const LL mod=1e9+7;
const int maxn=5e5+10;
int n;LL t;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
LL x[maxn],a[maxn],s[maxn];
//给定n个容器的位置xi和每个容器内部的物品个数ai,每个物品移动的代价是|xi-xj|,可承受的最大代价T
//求最多能把多少个物品集中到一个容器内
int main() { #ifdef shuaishuai freopen("in.txt","r",stdin); #endif // shuaishuai scanf("%d%lld",&n,&t); for(int i=1;i<=n;i++) x[i]=read(); for(int j=1;j<=n;j++) a[j]=read(), s[j]=a[j]+s[j-1]; LL l=1,r=1,m=1,ans=0; t/=2;
//首先固定左端点l,然后移动右端点r,对于该区间[l..r]移动m使该区间消耗代价最低
//当代价不足时,右移左端点,当代价足够时,右移右端点。每次移动都要求出当前区间的的最低代价
//相当优秀的的做法
//尺取法用到了一个性质就是,随着右端点右移,带权中位数点也会右移>=0个单位
//移动m的过程中代价的增加公式需要推导
while(r<=n) { t-=(x[r]-x[m])*a[r]; r++; while(l<=r) { while(m<r-1) { LL tmp=(s[l-1]+s[r-1]-s[m]*2)*(x[m+1]-x[m]); if(tmp<=0)break; t+=tmp; m++; } if(t>=0) break; t+=a[l]*(x[m]-x[l]); l++; } LL L=0,R=0; if(l>1) L=min(a[l-1],t/(x[m]-x[l-1])); if(r<=n) R=min(a[r],t/(x[r]-x[m])); ans=max(ans,s[r-1]-s[l-1]+max(L,R)); } cout<<ans<<endl; return 0; }

 

牛客网2018暑期ACM多校训练营(第二场)G transform 尺取法 带权中位数

原文:https://www.cnblogs.com/polya/p/9892493.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!