线段树&数状数组

线段树

单点修改,区间查询

#include<bits/stdc++.h>

using namespace std;

int n,q;
long long num[1000010];

struct tree
{
    int l,r;
    long long sum,max;
}t[4000010];

void BuildTree(int,int,int);

void Update(int,int,int,int,long long);

long long Query(int,int,int,int,int);

int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)scanf("%lld",num+i);
    BuildTree(1,1,n);
    for(int i=1;i<=q;i++)
    {
        int c;
        scanf("%d",&c);
        if(c==1)
        {
            int a;
            long long b;
            scanf("%d%lld",&a,&b);
            Update(1,1,n,a,b);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            printf("%lld\n",Query(1,1,n,a,b));
        }
    }
return 0;
}

void BuildTree(int id,int l,int r)
{
    int mid=(l+r)>>1;
    t[id].l=l;
    t[id].r=r;
    if(l==r)
    {
        t[id].sum=t[id].max=num[l];
        return;
    }
    BuildTree(id*2,l,mid);
    BuildTree(id*2+1,mid+1,r);
    t[id].sum=t[id*2].sum+t[id*2+1].sum;
//  t[id].max=max(t[id*2].max,t[id*2+1].max);
}

void Update(int id,int l,int r,int x,long long v)
{
    int mid=(l+r)>>1;
    if(l==r&&l==x)
    {
        t[id].sum+=v;
//      t[id].max+=v;
        return;
    }
    if(mid<x)
    {
        Update(id*2+1,mid+1,r,x,v);
    }
    else
    {
        Update(id*2,l,mid,x,v);
    }
    t[id].sum=t[id*2].sum+t[id*2+1].sum;
    //t[id].max=max(t[id*2].max,t[id*2+1].max);
}

long long Query(int id,int l,int r,int x,int y)
{
    int mid=(l+r)>>1;
    long long sum=0;
    if(x<=l&&y>=r)return t[id].sum;
    if(x<=mid)sum+=Query(id*2,l,mid,x,y);
    if(y>mid)sum+=Query(id*2+1,mid+1,r,x,y);
    return sum;
}

区间修改,单点查询

#include<bits/stdc++.h>

#define lson id*2,l,mid
#define rson id*2+1,mid+1,r

using namespace std;

int n,q;
int num[1000010];

struct node
{
    int l,r;
    int addmark;
    long long sum;
}tree[4000010];

void BuildTree(int,int,int);

long long Query(int,int,int,int);

void UpDate(int,int,int,int,int,long long);

void PushDown(int);

int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",num+i);
    }
    BuildTree(1,1,n);
    for(int i=1;i<=q;i++)
    {
        int k;
        scanf("%d",&k);
        if(k==1)
        {
            int t,p;
            long long v;
            scanf("%d%d%lld",&t,&p,&v);
            UpDate(1,1,n,t,p,v);
        }
        if(k==2)
        {
            int t;
            scanf("%d",&t);
            printf("%lld\n",Query(1,1,n,t));
        }
    }
return 0;
}

void BuildTree(int id,int l,int r)
{
    tree[id].l=l;
    tree[id].r=r;
    if(l==r)
    {
        tree[id].sum=num[l];
        return;
    }
    int mid=(l+r)>>1;
    BuildTree(lson);
    BuildTree(rson);
    tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
}

long long Query(int id,int l,int r,int x)
{
    if(l==r&&l==r)
    {
        return tree[id].sum;
    }
    PushDown(id);
    int mid=(l+r)>>1;
    if(x<=mid)return Query(lson,x);
    else if(x>mid)return Query(rson,x);
}

void UpDate(int id,int l,int r,int x,int y,long long val)
{
    if(x<=l&&y>=r)
    {
        tree[id].sum+=val*(l-r+1);
        tree[id].addmark+=val;
        return;
    }
    PushDown(id);
    int mid=(l+r)>>1;
    if(x<=mid)UpDate(lson,x,y,val);
    if(y>mid)UpDate(rson,x,y,val);
    tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
}

void PushDown(int id)
{
    if(tree[id].addmark!=0)
    {
        tree[id*2].sum+=tree[id].addmark*(tree[id*2].r-tree[id*2].l+1);
        tree[id*2+1].sum+=tree[id].addmark*(tree[id*2+1].r-tree[id*2+1].l+1);
        tree[id*2].addmark+=tree[id].addmark;
        tree[id*2+1].addmark+=tree[id].addmark;
        tree[id].addmark=0;
    }
}

区间修改,区间查询

#include<bits/stdc++.h>

using namespace std;

int n,q;
long long num[1000010];

struct tree
{
    int l,r;
    long long sum,addmark;
}t[4000010];

void BuildTree(int,int,int);

void Update(int,int,int,int,int,long long);

long long Query(int,int,int,int,int);

void PushDown(int);

int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)scanf("%lld",num+i);
    BuildTree(1,1,n);
    for(int i=1;i<=q;i++)
    {
        int o;
        scanf("%d",&o);
        if(o==1)
        {
            int a,b;
            long long c;
            scanf("%d%d%lld",&a,&b,&c);
            Update(1,1,n,a,b,c);
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            printf("%lld\n",Query(1,1,n,a,b));
        }
    }
return 0;
}

void BuildTree(int id,int l,int r)
{
    int mid=(l+r)>>1;
    t[id].l=l;
    t[id].r=r;
    if(l==r)
    {
        t[id].sum=num[l];
        return;
    }
    BuildTree(id*2,l,mid);
    BuildTree(id*2+1,mid+1,r);
    t[id].sum=t[id*2].sum+t[id*2+1].sum;
}

void Update(int id,int l,int r,int x,int y,long long v)
{
    int mid=(l+r)>>1;
    if(x<=l&&y>=r)
    {
        t[id].sum+=v*(r-l+1);
        t[id].addmark+=v;
        return;
    }
    PushDown(id);
    if(x<=mid)Update(id*2,l,mid,x,y,v);
    if(y>mid)Update(id*2+1,mid+1,r,x,y,v);
    t[id].sum=t[id*2].sum+t[id*2+1].sum;
}

long long Query(int id,int l,int r,int x,int y)
{
    int mid=(l+r)>>1;
    long long sum=0;
    if(x<=l&&y>=r)return t[id].sum;
    PushDown(id);
    if(x<=mid)sum+=Query(id*2,l,mid,x,y);
    if(y>mid)sum+=Query(id*2+1,mid+1,r,x,y);
    return sum;
}

void PushDown(int id)
{
    if(t[id].addmark!=0)
    {
        t[id*2].addmark+=t[id].addmark;
        t[id*2+1].addmark+=t[id].addmark;
        t[id*2].sum+=t[id].addmark*(t[id*2].r-t[id*2].l+1);
        t[id*2+1].sum+=t[id].addmark*(t[id*2+1].r-t[id*2+1].l+1);
        t[id].addmark=0;
    }
}

树状数组

单点修改,区间查询

#include<bits/stdc++.h>

#define lowbit id&-id

using namespace std;

int n,q;
int tree[1000010];

long long Query(int);

void Add(int,int);

int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;++i)
    {
        int a;
        scanf("%d",&a);
        Add(i,a);
    }
    for(int i=1;i<=q;++i)
    {
        int c;
        scanf("%d",&c);
        if(c==1)
        {
            int x,k;
            scanf("%d%d",&x,&k);
            Add(x,k);
        }
        if(c==2)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%lld\n",Query(y)-Query(x-1));
        }
    }
return 0;
}

void Add(int id,int x)
{
    while(id<=n)
    {
        tree[id]+=x;
        id+=lowbit;
    }
}

long long Query(int id)
{
    long long sum=0;
    while(id>=1)
    {
        sum+=tree[id];
        id-=lowbit;
    }
return sum;
}

区间修改,单点查询

不会

原文地址:https://www.cnblogs.com/Hdgs3-blog/p/10320345.html

时间: 2024-09-30 18:37:08

线段树&数状数组的相关文章

[ACM] Color the ball [线段树水题][数组开大]

Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色.但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗? Input 每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <= N).  当N

数状数组求逆序对

逆序对在很多地方用的到.以前都是用归并排序或线段树求,在<mato的文件管理>看到有人用树状数组求,很简单!整理如下: 思路: 首先,开一个大小为这些数的最大值的数组,作为树状数组. 然后,将各个数按顺序依次加入该数组.方法为:这个数大小对应的它在线段树中的位置,对这个位置上的数加1,并更新树状数组.所以当前树状数组中存着所有原数字序列中当前数前面的数,而getsum(i)就是 i 前面小于等于 i 的数的个数.i-getsum(i)-1也就是大于它的个数.这就是逆序对了. 把每一个的逆序对数

PAT 1009. Triple Inversions (35) 数状数组

Given a list of N integers A1, A2, A3,...AN, there's a famous problem to count the number of inversions in it. An inversion is defined as a pair of indices i < j such that Ai > Aj. Now we have a new challenging problem. You are supposed to count the

HDU 1394Minimum Inversion Number 数状数组 逆序对数量和

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 18543    Accepted Submission(s): 11246 Problem Description The inversion number of a given number sequence a1, a2, ..., a

一维数状数组区间修改,查询

模板题CODEVS-1082 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多少. 一维树状数组可以考虑用差分来做,但是扩展不到二维. 所以我们令di=(ai~an)的增量 思路和差分一样,可以扩展到二维(现在还没懂) #include<iost

sicily 1136(线段树+最大子数组)

题目链接:sicily 1136 解题思路: 要求区间内的最大子数组,而且访问可能很频繁,时间复杂度需要达到o(n*logn),于是就很自然地想到了线段树.我们可以用线段树来保存区间的最大子数组,但是仔细想想又不对劲了,如果访问的区间跨越了两个小区间怎么破,所以,这并不只是一个简单的求区间连续和的问题,还要有点小技巧. 最大子数组怎么得到的,还记得<算法导论>里面讲过一种用分治法来求最大子数组的方法吗(分治法之最大子数组)? 假设我们要求区间[low , high]的最大子数组,并且已知[lo

hdu 5057 Argestes and Sequence (数状数组+离线处理)

题意: 给N个数.a[1]....a[N]. M种操作: S X Y:令a[X]=Y Q L R D P:查询a[L]...a[R]中满足第D位上数字为P的数的个数 数据范围: 1<=T<= 501<=N, M<=1000000<=a[i]<=$2^{31}$ - 11<=X<=N0<=Y<=$2^{31}$ - 11<=L<=R<=N1<=D<=100<=P<=9 思路: 直接开tree[maxn][1

Minimum Inversion Number 数状数组

Minimum Inversion Number Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1394 Description The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that sat

线段树和树状数组问题补充

1.线段树的树高: 这里的n=r-l+1,至多2*(log2n-1)个点. 2.区间查询时,每层至多只有两个区间会被询问.(父亲被完全覆盖的孩子,在这一层不会被询问了.) 3.线段树的总的节点数 但实际上我们做线段树,开数组时,仅仅开两倍*n是不够的(这里指的是线段树的堆式储存). 然后用“构造法”求通项公式. 得到: 所以,在线段树的最底层,最大编号可能会很接近4*n,所以线段树储存空间要开到4倍. 4.区间查询