【模板】线段树(区间加)

代码复杂度较高的数据结构……写过的最长的模板(你才写过几个模板啊)

有点类似分块的思想……???

设置add的标记,省去一个个节点修改的很多时间

在修改&查询中不断维护父子关系

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#define ll long long
#define MAXN 1000001
#define leftson cur<<1
#define rightson cur<<1|1
#define mid ((l+r)>>1)
#define push_up ans[cur]=ans[leftson]+ans[rightson]
#define push_down lazyadd(leftson,l,mid,tag[cur]); lazyadd(rightson,mid+1,r,tag[cur]); tag[cur]=0
using namespace std;
ll ans[MAXN<<2],tag[MAXN<<2];
void build(ll cur,ll l,ll r)
{
    if (l==r)
    {
        scanf("%lld",&ans[cur]);
        return;
    }
    build(leftson,l,mid);
    build(rightson,mid+1,r);
    push_up;
}
inline void lazyadd(ll cur,ll l,ll r,ll delta)
{
    tag[cur]+=delta;
    ans[cur]+=delta*(r-l+1);
}
inline void change(ll adl,ll adr,ll cur,ll l,ll r,ll delta)
{
    if (adl<=l&&r<=adr)
    {
        ans[cur]+=delta*(r-l+1);
        tag[cur]+=delta;
        return;
    }
    push_down;
    if (adl<=mid) change(adl,adr,leftson,l,mid,delta);
    if (adr>mid)  change(adl,adr,rightson,mid+1,r,delta);
    push_up;
}
long long query(ll quel,ll quer,ll cur,ll l,ll r)
{
    if (quel<=l&&r<=quer)
    {
        return ans[cur];
    }
    push_down;
    ll answer=0;
    if (quel<=mid)
    {
        answer+=query(quel,quer,leftson,l,mid);
    }
    if (quer>mid)
    {
        answer+=query(quel,quer,rightson,mid+1,r);
    }
    return answer;
}
int main()
{
    ll n,m;
    scanf("%lld%lld",&n,&m);
    int cs;
    build(1,1,n);
    ll a,b,c;
    for (ll i=1;i<=m;i++)
    {
        scanf("%d",&cs);
        if (cs==1)
        {
            scanf("%lld%lld%lld",&a,&b,&c);
            change(a,b,1,1,n,c);
            continue;
        }
        scanf("%lld%lld",&a,&b);
        printf("%lld\n",query(a,b,1,1,n));
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Kan-kiz/p/10620906.html

时间: 2024-11-08 22:52:43

【模板】线段树(区间加)的相关文章

线段树区间加模板

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define LL long long #define l(x) (x<<1) #define r(x) ((x<<1)|1) using namespace std; struct Tre {

vijos 1659 河蟹王国 线段树区间加、区间查询最大值

河蟹王国 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 https://vijos.org/p/1659 Description 河蟹王国有一位河蟹国王,他的名字叫羊驼.河蟹王国富饶安定,人们和谐相处.有一天,羊驼国王心血来潮,想在一部分人中挑出最和谐的人.于是,羊驼国王将 他的子民排成了一列(==!!b汗~好长呀).每个人都有一个初始的和谐值.羊驼国王每次会选择一个区间[L,R],这个区间中和谐值最大的人就是国王选 出的人.而且,在某一时间,区间[L

算法模板——线段树区间修改区间求和

该模板实现的功能——进行区间的乘法和加法,以及区间的求和(1:乘法 2:加法 3:求和)详见BZOJ1798 1 type 2 vet=record 3 a0,a1:int64; 4 end; 5 var 6 i,j,k,l,m,n,a2,a3,a4:longint; 7 p:int64; 8 d1,d2,d:vet; 9 a,c:array[0..1000000] of int64; 10 b:array[0..1000000] of vet; 11 function min(x,y:long

线段树 区间加

#include<iostream> #include<queue> #include<cstdio> #include<math.h> #include<cstring> #include<algorithm> using namespace std; int n,Q; long long ans; long long sum[4000009]; int dx[4000009]; int a[2000009]; void build

「模板」 线段树——区间乘 &amp;&amp; 区间加 &amp;&amp; 区间求和

「模板」 线段树--区间乘 && 区间加 && 区间求和 <题目链接> 原来的代码太恶心了,重贴一遍. #include <cstdio> int n,m; long long p; class SegmentTree { private: struct Node { int l,r; long long v,mul,add; Node *c[2]; Node(int l,int r):l(l),r(r),mul(1LL),add(0LL) { c[

线段树 + 区间更新 + 模板 ---- 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

POJ 2777 Count Color (线段树区间更新加查询)

Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. There is a very long board with length L centimeter, L is a positive integer, so we can evenly d

线段树区间修改模板

本来打算把大白书第三章一口气攻下来的,但是这个线段树也是卡了好久. 不敢过题太快,怕自己走马观花到头来结果什么都不会. 可也不能再拖了,在做题中也许有更多的体会. 模板一:1 L R v 表示区间[L, R]所有元素都加上v2 L R   表示查询区间[L, R]的sum, min, maxsumv[o]的定义为:如果只执行节点o及其子孙节点的中的add操作,节点o对应区间中所有数之和 1 //线段树区间修改 2 //1 L R v 表示区间[L, R]所有元素都加上v 3 //2 L R 表示

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 #