“玲珑杯”ACM比赛 Round #13 B -- 我也不是B,倍增+二分!
2017-04-01 18:16
295 查看
B 我也不是B
这个题做了一下午,比赛两个小时还是没做出来,比完赛才知道要用一个倍增算法确定区间,然后再二分右端点。
题意:定义一个序列的混乱度为累加和:b[i]*v[i],b[i]为这个序列中第i小的数,v[]数组是给定的。如果当前加进来的数购车的数构成的序列的混乱度大于m,则将当前的序列扔掉,然后将变量C加一,现在给出要加进来的序列的顺序,和v[]数组,求最终C的值。
思路:枚举左端点,二分右端点,暴力判断混乱度与M的关系,如果Me为0,只能一个一个删除,那么二分貌似会将复杂度拉高,所以为了避免这种情况我们要用倍增算法确定二分区间,假设当前左端点为i,于是枚举一个k使得[i,i+2^k]刚好大于M,于是,我们要改变C的位置必定在[i+2^(k-1),i+2^k]内,然后对这个区间二分暴力判断。
好吧,本弱只想到了枚举左端点二分右端点,未曾想到用倍增法进一步确定区间减少二分次数。也算学到了。const int N=1e6+10;
int n;
ll m,a
,v
,b
,num
;
bool find(int l,int r)
{
int len=0;
ll sum=0;
for(int i=l; i<=r; i++) b[len++]=a[i];
sort(b,b+len);
for(int i=0; i<len; i++)
{
sum+=b[i]*v[i];
if(sum>m) return true;
}
return false;
}
int main()
{
while(~scanf("%d%lld",&n,&m))
{
for(int i=0; i<n; i++) scanf("%lld",&a[i]);
for(int i=0; i<n; i++) scanf("%lld",&v[i]);
int c=0,j=0;
for(int i=0; i<n; i++) //枚举左端点,二分右端点
{
int k,ans=0,l=i+1,r=n-1;
for(k=1; k<n; k*=2) if(find(i,i+k)) break;
l=i+k/2,r=i+k;
while(l<r)
{
int mid=(l+r)/2;
if(find(i,mid)) r=mid;
else l=mid+1;
}
for(i; i<=l; i++)
{
if(i==l)
{
num[i]=++c;
break;
}
num[i]=c;
}
}
for(int i=0; i<n; i++)
{
printf("%d",num[i]);
if(i!=n-1) printf(" ");
else printf("\n");
}
}
return 0;
}
相关文章推荐
- “玲珑杯”ACM比赛 Round #13 B -- 我也不是B(二分排序)
- 二分+倍增思想 “玲珑杯”ACM比赛 Round #13/B
- “玲珑杯”ACM比赛 Round #19 B.Buildings【二分+RMQ】
- “玲珑杯”ACM比赛 Round #13
- “玲珑杯”ACM比赛 Round #19题解&源码【A,规律,B,二分,C,牛顿迭代法,D,平衡树,E,概率dp】
- “玲珑杯”ACM比赛 Round #13 题解&源码
- “玲珑杯”ACM比赛 Round #19 B -- Buildings (RMQ + 二分)
- 玲珑杯”ACM比赛 Round #15 D 咸鱼商店【二分+01背包】
- “玲珑杯”ACM比赛 Round #18 C -- 图论你先敲完模板(dp)
- Lonlife-ACM 1000 - Spoon Devil's 3-D Matrix(最小生成树)——“玲珑杯”acm比赛-试运行赛
- “玲珑杯”ACM比赛 Round #19 E.Expected value of the expression【Dp】
- “玲珑杯”ACM比赛 Round #23 C -- 你居然不吃巧克力(贪心+优先队列)
- “玲珑杯”ACM比赛 Round #16 Down the Rabbit Hole
- “玲珑杯”ACM比赛 Round #21【石子合并O(n^2)】
- 玲珑杯”ACM比赛 Round #11【待补】
- 玲珑杯 - 我也不是B 倍增+二分
- “玲珑杯”ACM比赛 Round #12题解&源码
- “玲珑杯”ACM比赛 Round #18 C(dp)
- “玲珑杯”ACM比赛 Round #19 A.A simple math problem【打表找规律】
- 玲珑杯1052 - See car——STL集合的应用(“玲珑杯”ACM比赛 Round #4 )