• 线段树


    树状数组就是个辣鸡

    不扯了

    先给链接

    线段树

    皮这么一下我很开心

    线段树区间加

    #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;
    }
    

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

  • 相关阅读:
    HDU 1698 Just a Hook(线段树区间替换)
    NBOJv2 1034 Salary Inequity(DFS序+线段树区间更新区间(最值)查询)
    NBOJv2 1004 蛤玮打扫教室(线段树区间更新区间最值查询)
    NBOJv2 1050 Just Go(线段树/树状数组区间更新单点查询)
    POJ 3468 A Simple Problem with Integers(线段树区间更新区间查询)
    HDU 1754 I Hate It(线段树单点更新区间最值查询)
    HDU 1166敌兵布阵+NOJv2 1025: Hkhv love spent money(线段树单点更新区间查询)
    GDUT——1169: Krito的讨伐(优先队列BFS)
    HDU——2444The Accomodation of Students(BFS判二分图+最大匹配裸题)
    HDU——1045Fire Net(最大匹配)
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/8494693.html
Copyright © 2020-2023  润新知