前缀和or线段树____计数少女(2016swust信息院赛)

    在山的那边海的那边有一位美丽的少女。因为少女诚实善良且有着浩瀚的胸怀,所以爱慕着她的世人们都称她为浩姐。    

    一天,一位垂涎于浩姐美色的大魔王古刑岳将浩姐敲晕带回了自己的魔窟,锁在了卧室里面就迫不及待地出去准备结婚事宜了。待浩姐醒来,看见一只追风少年飘在她的面前,追风少年对她说:“美丽的少女啊,你被凶恶的大魔王抓住了,我现在给你N把宝剑,编号从1-N,每把宝剑的初始攻击力都为0,所以我要对这些宝剑进行祝福,祝福次数为M次,然后由你自己选择一把攻击力最高的宝剑,手刃大魔王。”   

    每次祝福会给出四个整数x,y,a,d,表示将编号为i的宝剑的攻击力增加F[i],其中x <= i <= y。计算如下:   

    1.如果i == x,那么F[i] = a + d  

    2.如果x < i <= y,那么F[i] = F[i-1] + d

    输入第一行为两个整数N,M。N为宝剑数量,M为祝福次数。
    接下来M行,每行四个整数x , y , a , d。
    其中:N,M为不大于105的正整数,1 <= x <= y <= N,0 <= a,d <= 105;
    输出两个整数,第一个数为攻击力最高的那把宝剑的编号,如果有多把,输出编号最小的;第二个数为最高攻击力。
5 2
2 4 2 3
1 1 4 0

分析:题意很好理解,不过题目的描述会让人直接联想到线段树来做这道题,不过观察题目可以发现这道题只有一次询问,所以我们可以通过标记前缀数组来做这个题目。


代码:

#include <stdio.h>
#include <string.h>
 
long long arr[100010];
long long s[100010];
long long d[100010];
int n,m;
int main()
{
    int i;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int x,y;
        long long a,b;
        memset(arr,0,sizeof(arr));
        memset(s,0,sizeof(s));
        memset(d,0,sizeof(d));
        for(i = 0 ; i < m ; i ++)
        {
            scanf("%d%d%lld%lld",&x,&y,&a,&b);
            d[x] += b;
            s[x] += a;
            s[y+1] -= (a+(y-x+1)*b);
            d[y+1] -= b;
        }
        long long step = 0;
        long long D = 0;
        for(i = 1 ; i <= n ; i ++)
        {
            D += d[i];
            step += D;
            step += s[i];
            arr[i] += step;
        }
        int index = 1 ;
        for( i = 1 ; i <= n ; i ++)
            if(arr[i] > arr[index])
            {
                index = i;
            }
        printf("%d %lld\n",index,arr[index]);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值