CDOJ1057-秋实大哥与花

秋实大哥与花

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

秋实大哥是一个儒雅之人,昼听笙歌夜醉眠,若非月下即花前。

所以秋实大哥精心照料了很多花朵。现在所有的花朵排成了一行,每朵花有一个愉悦值。

秋实大哥每天要对着某一段连续的花朵歌唱,然后这些花朵的愉悦值都会增加一个相同的值 v v( v v可能为负)。

同时他想知道每次他唱完歌后这一段连续的花朵的愉悦值总和是多少。

Input

第一行有一个整数 n n,表示花朵的总数目。

第二行包含 n n个整数 ai ai,表示第 i i朵花初始的愉悦值。

第三行包含一个整数 m m,表示秋实大哥唱了 m m天的歌。

接下来 m m行,每行包含三个整数 l l  r r  v v,表示秋实大哥对着 [l,r] [l,r]这个区间内的花朵歌唱,每朵花的愉悦值增加了 v v

1nmai|v|100000 1≤n,m,ai,|v|≤100000 1lrn 1≤l≤r≤n。

Output

输出共 m m行,第 i i行表示秋实大哥完成第 i i天的歌唱后,那一段花朵的愉悦值总和。

Sample Input Sample Output
3
0 0 0
3
1 2 1
1 2 -1
1 3 1
2
0
3


 

解题思路:题目需要处理的是区间更新以及区间求和,所以需要使用懒惰标记。
这是一道模板题,敲代码细心一点就可以了,不要出错。

ac代码:
#include <cstdio>  
#include <iostream>  
using namespace std;  
#define Max 100005  
#define ll long long  
ll sum[Max<<2]; //记录每个节点的sum值   
ll co[Max<<2];//延迟标记数组   
void Build(int l, int r, int rt)  
{  
    co[rt] = 0;//标记初始全部置0   
    if(l == r) {  
        scanf("%lld", &sum[rt]);  
        return ;  
    }  
    int m = (l + r) >>1;  
    Build(l, m, rt<<1);  
    Build(m+1, r, rt<<1|1);  
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];//递归得到非叶子节点的sum值   
}  
void Updown(int rt, int key)//向下标记函数   
{  
    if(co[rt])//如果有标记,即下面的区间需要处理   
    {  
        co[rt<<1] += co[rt];  //注意这里是相加,不是赋值   
        co[rt<<1|1] += co[rt];  //hdu这里是赋值,因为那是区间替换   
        sum[rt<<1] += (key - (key >> 1)) * co[rt];//左子树sum值相加更新   
        sum[rt<<1|1] += (key >> 1) * co[rt];//右子树sum值相加更新  
        co[rt]=0;//标记处理完后要清为0,因为更新已经结束,任务结束   
    }  
}  
void Updata(int L, int R, int d, int l, int r, int rt)//区间更新函数   
{  
    if(l >= L && r <= R)  
    {  
        co[rt] += d; //标记,为后面查询做准备   
        sum[rt] += (ll)d * (r - l +1);//该节点需要在这里处理,因为已经是最下面的了,不会再下去了   
        return ;  
    }  
    Updown(rt, r - l + 1);//向下延迟标记   
    int m = (l + r) >> 1;  
    if(L <= m)  Updata(L, R, d, l, m, rt<<1);  //这两行能节省大量时间   
    if(m < R)  Updata(L, R, d, m+1, r, rt<<1|1);// 标准写法,代码简介   
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];//回溯更新当前sum值   
}  
ll Quest(int L, int R, int l, int r, int rt)//查询函数   
{  
   if(l >= L && r <= R)  
   {  
    return sum[rt];  
   }  
   Updown(rt, r - l + 1);//必须要这一行,向下更新,很重要   
   int m = (l + r) >> 1;  
   ll ret = 0;  
    if(L <= m)  ret += Quest(L, R, l, m, rt<<1);//这两行递归求解和   
    if(m < R)  ret += Quest(L, R, m+1, r, rt<<1|1);  
    return ret;  
}  
int main()  
{  
    int N, Q;  
    scanf("%d", &N);  
    Build(1, N, 1);  
    int a,b;
    scanf("%d", &Q);
	ll d;  
    while(Q--)  
    {  
        scanf("%d%d%lld",&a, &b, &d);  
            Updata(a, b, d, 1, N, 1);  
	     printf("%lld\n", Quest(a, b, 1, N, 1));  
        }  
      return 0; 
	}  

题目链接: 点击打开链接http://acm.uestc.edu.cn/#/problem/show/1057
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值