线段树 区间更新模板

一个带区间修改的线段树求和模板:

int MAXN = 100005;
ll a[100005<<2],ans,p;
struct Tree {
    ll l,r;
    ll sum,add,mul;
} tree[100005<<2];
void pushdown(int tr,int len) {
    if(len==1)
        return;
    long long m=tree[tr].mul,a=tree[tr].add;
    tree[tr*2].sum=(tree[tr*2].sum*m%p+(len-(len>>1))*a%p)%p;
    tree[tr*2+1].sum=(tree[tr*2+1].sum*m%p+(len>>1)*a%p)%p;
    tree[tr*2].add=(tree[tr*2].add*m%p+a)%p;
    tree[tr*2+1].add=(tree[tr*2+1].add*m%p+a)%p;
    tree[tr*2].mul=tree[tr*2].mul*m%p;
    tree[tr*2+1].mul=tree[tr*2+1].mul*m%p;
    tree[tr].mul=1;
    tree[tr].add=0;
}
void pushup(ll  x) {
    ll  tmp=2*x;
    tree[x].sum=(tree[tmp].sum+tree[tmp+1].sum)%p;
}

void build(int l,int r,int x) {
    tree[x].l=l;
    tree[x].r=r;
    tree[x].add=0;
    tree[x].mul = 1;
    if(l==r) {
        tree[x].sum = a[l];
        return ;
    }
    int tmp=x<<1;
    int mid=(l+r)>>1;
    build(l,mid,tmp);
    build(mid+1,r,tmp+1);
    pushup(x);
}

void update(ll l,ll r,ll c1,ll c2,ll x) {    //c1代表乘法 c2代表加法
    pushdown(x,tree[x].r-tree[x].l+1);
    if(r<tree[x].l||l>tree[x].r)
        return ;
    if(l<=tree[x].l&&r>=tree[x].r) {
        tree[x].sum=(tree[x].sum*c1%p+c2*(tree[x].r-tree[x].l+1))%p;
        tree[x].mul=c1*tree[x].mul%p;
        tree[x].add=(tree[x].add*c1%p+c2)%p;
        return ;
    }
    ll  tmp=x<<1;
    update(l,r,c1,c2,tmp);
    update(l,r,c1,c2,tmp+1);
    pushup(x);
}
void query(ll l,ll r,ll x) {

    if(r<tree[x].l||l>tree[x].r)
        return ;
    if(l<=tree[x].l&&r>=tree[x].r) {
        ans+=tree[x].sum;
        return ;
    }
    pushdown(x,tree[x].r-tree[x].l+1);
    ll  tmp=x<<1;
    ll  mid=(tree[x].l+tree[x].r)>>1;
    if(r<=mid)
        query(l,r,tmp);
    else if(l>mid)
        query(l,r,tmp+1);
    else {
        query(l,mid,tmp);
        query(mid+1,r,tmp+1);
    }
}

原文地址:https://www.cnblogs.com/zinyy/p/9139079.html

时间: 2024-11-09 05:58:30

线段树 区间更新模板的相关文章

线段树 + 区间更新 + 模板 ---- poj 3468

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

POJ-3468 - A Simple Problem with Integers(线段树区间更新模板)

http://poj.org/problem?id=3468 Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of

FZU Problem 2171 防守阵地 II (线段树区间更新模板题)

http://acm.fzu.edu.cn/problem.php?pid=2171 成段增减,区间求和.add累加更新的次数. #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <string> #include <algorithm> #include <stri

CF#52 C Circular RMQ (线段树区间更新)

Description You are given circular array a0,?a1,?...,?an?-?1. There are two types of operations with it: inc(lf,?rg,?v) - this operation increases each element on the segment [lf,?rg] (inclusively) by v; rmq(lf,?rg) - this operation returns minimal v

(简单) POJ 3468 A Simple Problem with Integers , 线段树+区间更新。

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. 题意

hdu1698(线段树区间替换模板)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1698 题意: 第一行输入 t 表 t 组测试数据, 对于每组测试数据, 第一行输入一个 n , 表示钩子有 n 节, 编号为 1 ~ n, 每节钩子的初始价值为 1 , 接下来输入一个 q, 接着 q 行输入, 每行格式为 l, r, x, 表示讲区间 [l, r] 内的钩子价值变成 x , 求最终的总价值: 思路: 线段树区间替换模板 代码: 1 #include <iostream> 2 #

HDU 1689 Just a Hook 线段树区间更新求和

点击打开链接 Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 18894    Accepted Submission(s): 9483 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

Hdu 3966 Aragorn&#39;s Story (树链剖分 + 线段树区间更新)

题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x: 3:(Q, x) 查询节点x的权值为多少? 解题思路: 可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新 1 #include <cstdio> 2 #include