SDUTOJ3108-赏赏赏

赏赏赏

Time Limit: 2000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

B国大举进犯,A国根据地利设下埋伏获得全胜,战后A国王论功行赏,现在问题来了。
 
现在我们将问题简化,已知B国一共来了M个士兵,每个士兵的生命值为Hi,A国设置了N个据点,当士兵经过第j个据点时,生命值减少Wj,当士兵的生命值小于等于0时就会被当前这个据点杀死。由于地形原因士兵必须依次经过据点1,据点2,据点3. . . . . .据点N。
现在A国王想知道前M个据点的杀敌数为多少。

输入

多组输入。
对于每组数据,首先输入两个整数N,M(1 <= N <= 100000,1 <= M<= min(N, 10000))。
接下来的M行,每行一个整数Hi,代表第i个士兵的初始生命值。(1 <= Hi <= 10000000)
接下来的N行,每行一个整数Wj,代表第j个据点的攻击力。(0 <= Wi <= 10000)

输出

对于每组数据。
输出M行,每行一个整数代表第j个据点的杀敌数。

示例输入

3 3
1
2
3
1
1
1

示例输出

1
1
1
 
 
 
 
 
 
这题的一个简单方法就是把士兵的生命值从小到大排序,把从第1个据点到第j个据点的攻击力总和算出来,与士兵的生命值进行比较,当士兵的生命值小于等于到第j个据点的攻击力总和时,士兵就会在第j个据点被杀死,该据点的杀敌数加1即可,这样可以省很多功夫。(这么简单的题我竟然因为cin和cout超时了好多次= =以后一定不忘加std::ios::sync_with_stdio(false);〒_〒)
 
 
 
 

代码


#include <cstdio>   
#include <algorithm>   
  
using namespace std;   
  
int h[1001000],w[1000000],cont[1000000];   
  
int main()   
{   
    int n,m,i,j;   
    while(~scanf("%d%d",&n,&m))   
    {   
        for(i=0; i<m; i++)   
            scanf("%d",&h[i]);   
        sort(h,h+m);   
        for(i=0;i<n;i++)   
        {   
            scanf("%d",&w[i]);   
            w[i]=(i==0?w[i]:w[i-1]+w[i]);   
        }   
        for(i=0;i<m;i++)   
            cont[i]=0;   
        for(i=0,j=0;i<m&&j<m;)   
        {   
            if(h[j]<=w[i])   
            {   
                cont[i]++;   
                j++;   
            }   
            else  
                i++;   
        }   
        for(i=0;i<m;i++)   
            printf("%d\n",cont[i]);   
    }   
    return 0;   
} 


 
 
 
 
 
 
还有一种更简洁的办法,就是用二分查找的原理,通过lower_bound()这个函数来查找士兵的生命值第一次小于等于据点攻击力的位置,从而使该据点的杀敌数加一。

代码

 
 
 
 
 
 
#include <iostream>   
#include <cstring>   
#include <algorithm>   
  
using namespace std;   
  
int h[1000000],w[1000000],cont[1000000];   
  
int main()   
{   
    ios::sync_with_stdio(false);   
    int n,m,i;   
    while(cin>>n>>m)   
    {   
        memset(cont,0,sizeof(cont));   
        for(i=0;i<m;i++)   
            cin>>h[i];   
        for(i=0;i<n;i++)   
        {   
            cin>>w[i];   
            if(i!=0)   
                w[i]+=w[i-1];   
        }   
        for(i=0;i<m;i++)   
        {   
            int x=lower_bound(w,w+n,h[i])-w;   
            cont[x]++;   
        }   
        for(i=0;i<m;i++)   
            cout<<cont[i]<<endl;   
    }   
    return 0;   
} 


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值