线段树

树状数组就是个辣鸡

不扯了

先给链接

线段树

皮这么一下我很开心

线段树区间加

#include<iostream>
using namespace std;
struct node
{
    long long val;
    long long tag;
}tree[10000000];
long long in[10000000];
void build(long long root,long long start,long long end)
{
    tree[root].tag=0;
    if(start==end)
    {
        tree[root].val=in[start];
        return ;
    }
    long long mid=(start+end)/2;
    build(root*2,start,mid);
    build(root*2+1,mid+1,end);
    tree[root].val=tree[root*2].val+tree[root*2+1].val;
    return ;
}
void push(long long root,long long start,long long end,long long mid)
{
    if(tree[root].tag)
    {
        tree[root*2].tag+=tree[root].tag;
        tree[root*2+1].tag+=tree[root].tag;
        tree[root*2].val+=tree[root].tag*(mid-start+1);
        tree[root*2+1].val+=tree[root].tag*(end-mid);
        tree[root].tag=0;
    }
    return ;
}
void update(long long root,long long nstart,long long nend,long long ustart,long long uend,long long add) // cymbal
{
    if(nstart>uend||nend<ustart)
    {
        return ;
    }
    if(nstart>=ustart&&nend<=uend)
    {
        tree[root].tag+=add;
        tree[root].val+=add*(nend-nstart+1);
        return ;
    }
    long long mid=(nstart+nend)/2;
    push(root,nstart,nend,mid);
    update(root*2,nstart,mid,ustart,uend,add);
    update(root*2+1,mid+1,nend,ustart,uend,add);
    tree[root].val=tree[root*2].val+tree[root*2+1].val;
    return ;
}
long long check(long long root,long long nstart,long long nend,long long ustart,long long uend)
{
    if(nstart>uend||nend<ustart)
    {
        return 0;
    }
    if(nstart>=ustart&&nend<=uend)
    {
        return tree[root].val;
    }
    long long mid=(nstart+nend)/2;
    push(root,nstart,nend,mid);
    long long cym=check(root*2,nstart,mid,ustart,uend)
          +check(root*2+1,mid+1,nend,ustart,uend);
    return cym;
}
int main()
{
    cin.sync_with_stdio(false);
    long long l,m;
    cin>>l>>m;
    for(long long i=1;i<=l;i++)
        cin>>in[i];
    long long a,b;
    long long f,k;
    build(1,1,l);
    for(long long i=1;i<=m;i++)
    {
        cin>>f>>a>>b;
        if(f==1)
        {
            cin>>k;
            update(1,1,l,a,b,k);
        }
        if(f==2)
            cout<<check(1,1,l,a,b)<<endl;
    }
    return 0;
}

因为是区间加,在push懒标记时和要加上区间长度*懒标记

如果时区间大小的话就不用le。要根据实际情况设计push函数

在看一道区间乘和加的题

题目,顺便%%%RQY

这道题告诉了我们如何处理两种运算的关系
(如果不知到的话,看看洛谷题解就行了,洛谷还是很好的网站,最起码,它不baoza

#include<iostream>
using namespace std;
struct node
{
	long long val;
	long long tag1;//*
	long long tag2;//+
	node(){val=0;tag1=1;tag2=0;}
};
node tree[400000];
long long in[100010];
long long n,m,p;
void build(long long root,long long left,long long right)
{
	if(left==right)
	{
		tree[root].val=in[left]%p;
		return ;
	}
	long long mid=(left+right)/2;
	build(root*2,left,mid);
	build(root*2+1,mid+1,right);
	tree[root].val=tree[root*2].val+tree[root*2+1].val;
	tree[root].val%=p;
	return ;
}
void push_down(long long root,long long left,long long right,long long mid)
{
	tree[root*2].val=((tree[root*2].val*tree[root].tag1)%p+tree[root].tag2*(mid-left+1))%p;
	tree[root*2].tag1=(tree[root*2].tag1*tree[root].tag1)%p;
	tree[root*2].tag2=(tree[root*2].tag2*tree[root].tag1+tree[root].tag2)%p;
	tree[root*2+1].val=((tree[root*2+1].val*tree[root].tag1)%p+tree[root].tag2*(right-mid))%p;
	tree[root*2+1].tag1=(tree[root*2+1].tag1*tree[root].tag1)%p;
	tree[root*2+1].tag2=(tree[root*2+1].tag2*tree[root].tag1+tree[root].tag2)%p;
	tree[root].tag1=1;
	tree[root].tag2=0;
}
void updata1(long long root,long long nleft,long long nright,long long aleft,long long aright,long long value)
{
	if(nleft>aright||nright<aleft)
		return ;
	if(nleft>=aleft&&nright<=aright)
	{
		tree[root].val=(tree[root].val*value)%p;
		tree[root].tag1=(tree[root].tag1*value)%p;
		tree[root].tag2=(tree[root].tag2*value)%p;
		return ;
	}
	long long mid=(nleft+nright)/2;
	push_down(root,nleft,nright,mid);
	updata1(root*2,nleft,mid,aleft,aright,value);
	updata1(root*2+1,mid+1,nright,aleft,aright,value);
	tree[root].val=(tree[root*2].val+tree[root*2+1].val)%p;
	return ;
}
void updata2(long long root,long long nleft,long long nright,long long aleft,long long aright,long long value)
{
	if(nleft>aright||nright<aleft)
		return ;
	if(nleft>=aleft&&nright<=aright)
	{
		tree[root].val=(tree[root].val+value*(nright-nleft+1))%p;
		tree[root].tag2=(tree[root].tag2+value)%p;
		return ;
	}
	long long mid=(nleft+nright)/2;
	push_down(root,nleft,nright,mid);
	updata2(root*2,nleft,mid,aleft,aright,value);
	updata2(root*2+1,mid+1,nright,aleft,aright,value);
	tree[root].val=(tree[root*2].val+tree[root*2+1].val)%p;
	return ;
}
long long check(long long root,long long nleft,long long nright,long long aleft,long long aright)
{
	if(nleft>aright||nright<aleft)
		return 0;
	if(nleft>=aleft&&nright<=aright)
		return tree[root].val;
	long long mid=(nleft+nright)/2;
	push_down(root,nleft,nright,mid);
	long long ans=(
		    check(root*2,nleft,mid,aleft,aright)+
		    check(root*2+1,mid+1,nright,aleft,aright)
		   )%p;
	return ans;
}
int main() 
{
	cin.sync_with_stdio(false);
	cin>>n>>m>>p;
	for(long long i=1;i<=n;i++)
		cin>>in[i];
	build(1,1,n);
	long long a,b,c,d;
	for(long long i=1;i<=m;i++)
	{
		cin>>a;
		switch(a)
		{
			case 1:
					cin>>b>>c>>d;
					updata1(1,1,n,b,c,d);
					break;
			case 2:
					cin>>b>>c>>d;
					updata2(1,1,n,b,c,d);
					break;
			case 3:
					cin>>b>>c;
					cout<<check(1,1,n,b,c)<<endl;
					break;
		}
	}	 
	return 0;
}

同时也要注意数据范围,我就是载在了上面。

原文地址:https://www.cnblogs.com/Lance1ot/p/8494693.html