LightOJ 1164 - Horrible Queries(线段树啊 功能:区间增减和区间求和)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1164

World is getting more evil and it‘s getting tougher to get into the Evil League of Evil. Since the legendary Bad Horse has retired, now you have to correctly answer the evil questions of Dr. Horrible, who has a PhD in horribleness (but not in Computer Science).
You are given an array of n elements,which are initially all 0. After that you will be given q commands. They are -

1.      0 x y v - you have to add v to all numbers in the range of x to y (inclusive), where x and y are two indexes of the array.

2.      1 x y - output a line containing a single integer which is the sum of all the array elements between x and y (inclusive).

The array is indexed from 0 to n - 1.

Input

Input starts with an integer T (≤ 5), denoting the number of test cases.

Each case contains two integers n (1 ≤ n ≤ 105) and q (1 ≤ q ≤ 50000). Each of the next q lines contains a task in one of the following form:

0 x y v (0 ≤ x ≤ y < n, 1 ≤ v ≤ 1000)

1 x y (0 ≤ x ≤ y < n)

Output

For each case, print the case number first. Then for each query ‘1 x y‘, print the sum of all the array elements between x and y.

Sample Input

Output for Sample Input


2

10 5

0 0 9 10

1 1 6

0 3 7 2

0 4 5 1

1 5 5

20 3

0 10 12 1

1 11 12

1 19 19


Case 1:

60

13

Case 2:

2

0

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l , mid , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
#define LL __int64
const LL maxn = 111111;
LL add[maxn<<2];
LL sum[maxn<<2];//求和
void PushUp(LL rt)
{
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(LL rt,LL len)
{
    if (add[rt])
    {
        add[rt<<1] += add[rt];
        add[rt<<1|1] += add[rt];

        sum[rt<<1] += add[rt] * (len - (len >> 1));
        sum[rt<<1|1] += add[rt] * (len >> 1);//更新右儿子的和
        add[rt] = 0;
    }
}
void build(LL l,LL r,LL rt)
{
    add[rt] = 0;//初始化为所有结点未被标记
    if (l == r)
    {
        //scanf("%lld",&sum[rt]);
        sum[rt] = 0;
        return ;
    }
    LL mid = (l + r) >> 1;
    build(lson);
    build(rson);
    PushUp(rt);
}
void update(LL L,LL R,LL c,LL l,LL r,LL rt)
{
    if (L <= l && r <= R)
    {
        add[rt] += c;
        sum[rt] += (LL)c * (r - l + 1);//更新代表某个区间的节点和,该节点不一定是叶子节点
        return ;
    }
    PushDown(rt , r - l + 1);
    LL mid = (l + r) >> 1;
    if (L <= mid)
        update(L , R , c , lson);//更新左儿子
    if (mid < R)
        update(L , R , c , rson);//更新右儿子
    PushUp(rt);
}
LL query(LL L,LL R,LL l,LL r,LL rt)
{
    if (L <= l && r <= R)
    {
        return sum[rt];
    }
    PushDown(rt , r - l + 1);
    LL mid = (l + r) >> 1;
    LL ret = 0;
    if (L <= mid)
        ret += query(L , R , lson);
    if (mid < R)
        ret += query(L , R , rson);
    return ret;
}
int main()
{
    LL N , Q;
    LL t;
    LL cas = 0;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld%lld",&N,&Q);//N为节点数
        build(1 , N , 1); //建树
        printf("Case %d:\n",++cas);
        while (Q--)//Q为询问次数
        {
            //char op[2];
            LL op;
            LL a , b , c;
            scanf("%lld",&op);
            if(op == 1)
            {
                scanf("%lld%lld",&a,&b);
                printf("%lld\n",query(a+1 , b+1 , 1 , N , 1));
            }
            else if(op == 0)
            {
                scanf("%lld%lld%lld",&a,&b,&c);//c为区间a到b增加的值
                update(a+1 , b+1 , c , 1 , N , 1);
            }
        }
    }
    return 0;
}
/*
2
10 5
0 0 9 10
1 0 6
0 3 7 2
0 4 5 1
1 5 5
20 3
0 10 12 1
1 11 12
1 19 19
*/
时间: 2024-08-23 09:23:00

LightOJ 1164 - Horrible Queries(线段树啊 功能:区间增减和区间求和)的相关文章

HDU4027 Can you answer these queries 线段树区间求和+剪枝

给了你n,然后n个数字在一个数组中,接下来m个询问,每个询问三个数字 t,x,y,若t==0,那么修改区间[x,y]的每一个值,变为原来每个位置上的数 开根号取整,若t==1,那么对区间[x,y]求和 由于n,m,很大,所以树状数组铁定超时,若直接用线段树来做区间修改,那么也是超时,这类题目没别的方法了,静心剪枝,发现题目给的数据范围为2^63,有没有发现,2^63开根号 绝对不需要开10次,就能到1,到1以后就不需要再开了,意思就是若有某个区间[x,y]每一个点的值都为1时,这一段区间事实上是

HDU 4027 Can you answer these queries? (线段树+区间点修改)

题意:给你 n 个数,m个询问(c,x,y) c==0 把x,y区间的值变为原来的平方根(向下取整) c==1 计算x,y区间的和. 利用1的开方永远为1剪枝.. #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> //#include<map> #include<cmath> #include<iostream> #include

HDU 4027 Can you answer these queries?(线段树,区间更新,区间查询)

题目 线段树 简单题意: 区间(单点?)更新,区间求和 更新是区间内的数开根号并向下取整 这道题不用延迟操作 //注意: //1:查询时的区间端点可能前面的比后面的大: //2:优化:因为每次更新都是开平方,同一个数更新有限次数就一直是1了,所以可以这样优化 #include <stdio.h> #include<math.h> #define N 100010 #define LL __int64 #define lson l,m,rt<<1 #define rson

HDU 4027 Can you answer these queries? 线段树裸题

题意: 给定2个操作 0.把区间的每个数sqrt 2.求和 因为每个数的sqrt次数很少,所以直接更新到底,用个标记表示是否更新完全(即区间内的数字只有0,1就不用再更新了) #include<stdio.h> #include<iostream> #include<algorithm> #include<vector> #include<cmath> #include<queue> #include<set> #incl

hdu4027-Can you answer these queries?(线段树)

Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 8330    Accepted Submission(s): 1904 Problem Description A lot of battleships of evil are arranged in a line before

POJ 3468-A Simple Problem with Integers(线段树:成段更新,区间求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 62228   Accepted: 19058 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

【线段树】HDU 3397 Sequence operation 区间合并

操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters into '1's in [a , b] 2 a b change all '0's into '1's and change all '1's into '0's in [a, b] Output operations: 3 a b output the number of '1's in [a,

POJ 3468 A Simple Problem with Integers(线段树模板之区间增减更新 区间求和查询)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 140120   Accepted: 43425 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type o

LightOJ 1097 - Lucky Number 线段树

http://www.lightoj.com/volume_showproblem.php?problem=1097 题意:一个自然数序列,先去掉所有偶数项,在此基础上的序列的第二项为3,则删去所有3的倍数的元素,再是7……重复操作,最后问第n项的值 思路:使用线段树构造序列,对一个数进行标记是否已被删去,和为元素个数.由于样例给出了大小,所以很容易控制空间. /** @Date : 2016-12-05-19.34 * @Author : Lweleth ([email protected])