二分+倍增思想 “玲珑杯”ACM比赛 Round #13/B

题址:http://www.ifrog.cc/acm/problem/1112


小 L 有一串 QQ 个数排成一排,从左往右是 A1A1 开始一直到 AQAQ,它一直很喜欢这串数。

有一天,小 L 去高考报名了,小 J 和小 N 过来用这串数玩游戏。

一开始,小 N 手上有一个空序列,定义变量C:=0C:=0。小 J 从左往右依次把序列中的数取出,放到小 N 手上序列的最右边,如果放完之后,整个序列的混乱度超过了 MM,小 N 就会把手上的所有数全部扔掉,然后令 C:=C+1C:=C+1

定义一个长度为 KK 序列的混乱度 S=Ki=1Bi×ViS=∑i=1KBi×Vi,其中 BiBi 表示序列中第 ii 小的数,VV 为一个给定的序列。

小 J 和小 N 想知道,加入每个数之后,CC 是多少。

INPUT
第一行两个整数QQMM接下来一行QQ个整数, 第ii个整数表示AiAi接下来一行QQ个整数, 第ii个整数表示ViVi
OUTPUT
一行QQ个整数, 第ii个整数表示加入第ii个数之后的CC, 相邻两个整数之间用空格隔开, 注意最后一个数后不要输出空格输出完请换行
SAMPLE INPUT
5 1
1 3 2 5 4
1 1 1 1 1
SAMPLE OUTPUT
0 1 2 3 4
HINT
1Q300000,0M1018,1Ai108,1Vi1041≤Q≤300000,0≤M≤1018,1≤Ai≤108,1≤Vi≤104对于所有的1iQ1,ViVi+11≤i≤Q−1,Vi≤Vi+1

题意: 混乱度为当前的序列排好序后与V【】的乘积和,
当混乱度大于M时,把当前序列全部扔掉,并且让c+1,
输出每个数的c值是多少。
思路:左端点固定,倍增找右端点的范围,二分找右端点,然后左端点移到右端点+1,重复这个过程;

比赛的时候没听说过倍增思想,一直超时。
这个思想挺重要的,学到了0.0
AC代码如下:
#define N 1000010
int a[N],v[N],num[N],p[N];
int n;
LL m;
int find(int x,int y)
{
    LL sum=0;
    int len=0;
    for(int i=x;i<=y;i++)
        p[len++]=a[i];
    sort(p,p+len);
    for(int i=0;i<len;i++)
        sum+=p[i]*v[i];
        if(sum>m)return 1;
        else return 0;
}
int main()
{
    int ans=0;
    scanf("%d%lld",&n,&m);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
       for(int i=0;i<n;i++)
            scanf("%d",&v[i]);
            for(int i=0;i<n;i++)
            {
                int k;
                for(k=1;k<n;k*=2)if(find(i,i+k))break;
                int l=i+k/2,r=i+k,mid;
                while(l<r)
                {
                    mid=(r+l)/2;
                    if(find(i,mid))r=mid;
                    else l=mid+1;
                }
                for(;i<=l;i++)
                {
                    if(i==l)
                    {
                        num[i]=++ans;
                        break;
                    }
                    num[i]=ans;
                }
            }
            for(int i=0;i<n;i++)
            {
                if(i)
                    printf(" ");
                printf("%d",num[i]);
            }
            printf("\n");
}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值