线段树复合标记

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
int a[100005],p;
static const int MAXN=400000;
struct  Segment_tree///1.把一段区间变成同一个数,2求任意区间的和
{
    int size;///区间容量
    struct Node
    {
        long long a;
        long long b;
        long long sum;
        int len;
        void fun(long long a1,long long b1)///复合一个新标记
        {
            a=a*a1%p;
            b=(b*a1+b1)%p;
        }
        void use()
        {
            sum=(sum*a+b*len)%p;
        }
        void clear()
        {
            a=1;
            b=0;
        }
        bool islazy()
        {
            return a!=1||b!=0;
        }
    } node[MAXN];
    void update(int pos)///结点更新函数
    {
        if(pos>=size)///判断是叶子
        {
            node[pos].sum=a[pos-size]%p;
        }
        else
        {
            node[pos].sum=(node[pos<<1].sum+node[pos<<1^1].sum)%p;
            node[pos].len=node[pos<<1].len+node[pos<<1^1].len;
        }
        if(node[pos].islazy())///注意如果有懒惰标记的话要把懒惰标记用掉
            node[pos].use();
    }
    void build(int n)///申请空空间
    {
        n+=4;///保险起见,申请时,申请得稍微大一点
        size=1;
        while(size<n)///计算几个刚好能套住整个区间的区间容量
            size<<=1;
        memset(node,0,sizeof(node));
    }
    void build(int n,int arr[])///申请空间,并建树
    {
        build(n);
        int i;
        for(i=1; i<=n; i++)
        {
            node[i+size].sum=arr[i];///把数组铺在底层
            node[i+size].clear();
        }
        for(i=size; i<size+size; i++)
        {
             node[i].len=1;
             node[i].clear();
        }
        for(i=size-1; i>0; i--)
        {
            node[i].clear();
            update(i);///数值更新上去
        }
    }
    void putdown(int s,int t)///将标记放下
    {
        if(s>1)///判断是否到顶,没达到顶继续往上爬
        {
            putdown(s>>1,t>>1);
        }
        if(node[s].islazy())///判断有没有标记,如果有标记话,下放给孩子
        {
            node[s<<1].fun(node[s].a,node[s].b);
            node[s<<1^1].fun(node[s].a,node[s].b);
            node[s].clear();
        }
        if(node[t].islazy())
        {
            node[t<<1].fun(node[t].a,node[t].b);
            node[t<<1^1].fun(node[t].a,node[t].b);
            node[t].clear();
        }
    }
    void add(int l,int r,int x)
    {
        int s=l+size-1;
        int t=r+size+1;
        putdown(s>>1,t>>1);
        ///更新标记>更新值>查询查询值
        for(; s^t^1; s>>=1,t>>=1)
        {
            // printf("[%d %d]\n",s,t);
            if(~s&1)
                node[s^1].fun(1,x);
            if(t&1)
                node[t^1].fun(1,x);
            update(s);
            update(t);
            update(s^1);
            update(t^1);
        }
        while(s)///一直更新到顶
        {
            update(s);
            update(s^1);
            s>>=1;
        }
    }
    void mul(int l,int r,int x)
    {
        int s=l+size-1;
        int t=r+size+1;
        putdown(s>>1,t>>1);
        ///更新标记>更新值>查询查询值
        for(; s^t^1; s>>=1,t>>=1)
        {
            // printf("[%d %d]\n",s,t);
            if(~s&1)
                node[s^1].fun(x,0);
            if(t&1)
                node[t^1].fun(x,0);
            update(s);
            update(t);
            update(s^1);
            update(t^1);
        }
        while(s)///一直更新到顶
        {
            update(s);
            update(s^1);
            s>>=1;
        }
    }
    int query(int l,int r)
    {
        int s=l+size-1;
        int t=r+size+1;
        putdown(s>>1,t>>1);
        long long sum=0;
        ///更新标记>更新值>查询查询值
        for(; s^t^1; s>>=1,t>>=1)
        {
            update(s);
            update(t);
            update(s^1);
            update(t^1);
            //    printf("[%d %d]\n",s,t);
            if(~s&1)
            {
                sum+=node[s^1].sum;
            }
            if(t&1)
            {
                sum+=node[t^1].sum;
            }
        }
        while(s)///一直更新到顶
        {
            update(s);
            update(s^1);
            s>>=1;
        }
        return sum%p;
    }
    void put()
    {
        int i=1,j=1,s=size*4,k,len=3;
        for(i=1; i<=2*size-1; i++)
        {
            if(i==j)
            {
                puts("");
                j<<=1;
                s>>=1;
                for(k=0; k<len*(s/2-1); k++)
                    printf(" ");

            }
            printf("%3d",node[i].islazy());
            for(k=0; k<len*(s-1); k++)
                printf(" ");

        }
        puts("");
    }
} tree;
int main()
{
    int n,i,t,x,y,cas=1,l,r,m,op;
    scanf("%d%d",&n,&p);
    for(i=1; i<=n; i++)
        scanf("%d",&a[i]);
    tree.build(n,a);
   // tree.put();
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d%d%d",&l,&r,&x);
            tree.mul(l,r,x);
        }
        else if(op==2)
        {
            scanf("%d%d%d",&l,&r,&x);
            tree.add(l,r,x);

        }
        else
        {
            scanf("%d%d",&l,&r);
            printf("%d\n",tree.query(l,r));
        }

    }
 return 0;
}

 

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 春招至今,你的战绩如何? #
10354次浏览 92人参与
# 你的实习产出是真实的还是包装的? #
1836次浏览 42人参与
# MiniMax求职进展汇总 #
23970次浏览 308人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
7537次浏览 43人参与
# 简历第一个项目做什么 #
31643次浏览 333人参与
# 重来一次,我还会选择这个专业吗 #
433423次浏览 3926人参与
# 米连集团26产品管培生项目 #
5894次浏览 215人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
187071次浏览 1122人参与
# 牛客AI文生图 #
21418次浏览 238人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152338次浏览 887人参与
# 研究所笔面经互助 #
118892次浏览 577人参与
# 简历中的项目经历要怎么写? #
310182次浏览 4202人参与
# AI时代,哪些岗位最容易被淘汰 #
63576次浏览 813人参与
# 面试紧张时你会有什么表现? #
30502次浏览 188人参与
# 你今年的平均薪资是多少? #
213063次浏览 1039人参与
# 你怎么看待AI面试 #
179990次浏览 1245人参与
# 高学历就一定能找到好工作吗? #
64323次浏览 620人参与
# 你最满意的offer薪资是哪家公司? #
76474次浏览 374人参与
# 我的求职精神状态 #
448028次浏览 3129人参与
# 正在春招的你,也参与了去年秋招吗? #
363346次浏览 2638人参与
# 腾讯音乐求职进展汇总 #
160627次浏览 1111人参与
# 校招笔试 #
470762次浏览 2964人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务