NYOJ 1068 ST(线段树之 成段更新+区间求和)

ST

时间限制:1000 ms  |  内存限制:65535 KB

难度:1

描述

“麻雀”lengdan用随机数生成了后台数据,但是笨笨的他被妹纸的问题给难住了。。。

已知lengdan生成了N(1=<N<=10005)个随机整数,妹子对这些数可能有以下几种操作或询问:

1,A a b c 表示给区间a到b内每个数都加上c;

2,S a b  表示输出区间a到b内的和;

3,Q a b 表示区间a到b内的奇数的个数;

为了使妹纸不口渴,所以我们决定妹纸的询问次数少一点,即(1=<M<=10000,M为询问次数)。

输入
多组测试数据。

每组测试数据第一行包含两个数N,M,表示N个整数,执行M次询问或操作。

紧接着一行输入N个整数,输入数据保证在int范围内。

接下来M行,每行输入一种操作。

输出
每次对于操作2和3,输出结果。
样例输入
5 5
1 2 3 4 5
Q 1 4
S 1 5
A 1 4 1
S 1 5
Q 2 5
样例输出
2
15
19
3
简单的线段树成段更新+区间求和,只是附加了求区间内的奇数个数。由于之前没有写过线段树成段更新的题目,导致因为一条向下更新的语句忘记写,调了一个上午才发现错误。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 10010;
#define lson l, mid, root<<1
#define rson mid+1, r, root<<1|1
struct node
{
    int l, r;
    LL sum, odd, add;
}a[N<<2];
void PushUp(int root)
{
    a[root].sum = a[root<<1].sum + a[root<<1|1].sum;
    a[root].odd = a[root<<1].odd + a[root<<1|1].odd;
}
void PushDown(int len, int root)
{
    if(a[root].add)
    {
        a[root<<1].add += a[root].add;
        a[root<<1|1].add += a[root].add;
        a[root<<1].sum += LL(len - (len>>1)) * a[root].add;
        a[root<<1|1].sum += LL(len>>1) * a[root].add;
        if(a[root].add % 2 == 1)
        {
            a[root<<1].odd = len - (len>>1) - a[root<<1].odd;
            a[root<<1|1].odd = (len>>1) - a[root<<1|1].odd;
        }
        a[root].add = 0;
    }
}
void build_tree(int l, int r, int root)
{
    a[root].l = l;
    a[root].r = r;
    a[root].add = 0;
    a[root].odd = 0;
    if(l == r)
    {
        scanf("%lld",&a[root].sum);
        if(a[root].sum % 2 == 1)
            a[root].odd = 1;
        return;
    }
    int mid = (l + r) >> 1;
    build_tree(lson);
    build_tree(rson);
    PushUp(root);
}
void update(int l, int r, int root, LL k)
{
    if(l <= a[root].l && r >= a[root].r)
    {
        a[root].add += k;
        a[root].sum += LL(a[root].r - a[root].l + 1) * k;
        if(k % 2 == 1)
            a[root].odd = (a[root].r - a[root].l + 1) - a[root].odd;
        return;
    }
    PushDown(a[root].r - a[root].l + 1, root);
    int mid = (a[root].l + a[root].r) >> 1;
    if(l <= mid) update(l, r, root<<1, k);
    if(r > mid) update(l, r, root<<1|1, k);
    PushUp(root);
}
LL Query(int l, int r, int root, char ch)
{
    if(l <= a[root].l && r >= a[root].r)
    {
        if(ch == 'Q') return a[root].odd;
        else if(ch == 'S') return a[root].sum;
    }
    PushDown(a[root].r - a[root].l + 1, root);
    LL ans = 0;
    int mid = (a[root].l + a[root].r) >> 1;
    if(l <= mid) ans += Query(l, r, root<<1, ch);
    if(r > mid) ans += Query(l, r, root<<1|1, ch);
    return ans;
}
int main()
{
    int n, m, i, x, y;
    LL z;
    char ch[5];
    while(~scanf("%d%d",&n,&m))
    {
        build_tree(1, n, 1);
        while(m--)
        {
            scanf("%s",ch);
            if(ch[0] == 'A')
            {
                scanf("%d%d%lld",&x,&y,&z);
                update(x, y, 1, z);
            }
            else
            {
                scanf("%d%d",&x,&y);
                printf("%lld\n", Query(x, y, 1, ch[0]));
            }
        }
    }
    return 0;
}

NYOJ 1068 ST(线段树之 成段更新+区间求和)

时间: 2024-12-16 21:19:14

NYOJ 1068 ST(线段树之 成段更新+区间求和)的相关文章

hdu 1698 线段树(成段替换 区间求和)

一条钩子由许多小钩子组成 更新一段小钩子 变成铜银金 价值分别变成1 2 3 输出最后的总价值 Sample Input11021 5 25 9 3 Sample OutputCase 1: The total value of the hook is 24. 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # includ

hdu 1698 Just a Hook(线段树之 成段更新)

Just a Hook                                                                             Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description In the game of DotA, Pudge's meat hook is actually the mos

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 (线段树,成段更新,区间合并)

http://acm.hdu.edu.cn/showproblem.php?pid=3397 Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5801    Accepted Submission(s): 1713 Problem Description lxhgww got a sequence

hdu 1698 Just a Hook(线段树,成段更新,懒惰标记)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 18384    Accepted Submission(s): 9217 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible thing

POJ 3468 线段树(成段更新,区间求和)

题目链接:http://poj.org/problem?id=3468 题意:给定一个数列,每次操作可以是将某区间数字都加上一个相同的整数,也可以是询问一个区间中所有数字的和,对每次询问输出结果. 这个线段树运用了应用了add域优化,每个节点除了用value记录当前节点对应区间元素的和之外,还要用add域记录当前节点对应区间每个元素的增量.这样,没必要每次更新都要更新value更新到最底层每一个点,只需要将增量记录在某父节点的add域中即可,如果下次查询或者更新操作的是该父节点对应区间的子区间,

POJ 3468 A Simple Problem with Integers //线段树的成段更新

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 59046   Accepted: 17974 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 1698 Just a Hook(线段树lazy成段更新)

Just a Hook Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sticks which are of the same length. Now Pudge wants to do some ope

hdu 4107 Gangster 线段树(成段更新)

维护每个区间的最小值和最大值,update的时候判断low[rt]与up[rt]和p的大小关系,进行更新操作. 卡时卡得很紧. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 usin