社区讨论

求助大神。。

P3373【模板】线段树 2参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mi6m2f3z
此快照首次捕获于
2025/11/20 07:05
4 个月前
此快照最后确认于
2025/11/20 07:05
4 个月前
查看原帖
CPP
#include <bits/stdc++.h>
#define LL long long 
#define lson (o<<1)
#define rson (o<<1|1)
using namespace std;
const int MAXN = 200000;
const int INF = 1<<30;
int n, m, p, ans_sum=0;
LL a[MAXN], ans[MAXN];
struct Segment_Tree
{
    LL sumv[MAXN*4], optv[MAXN*4], optmul[MAXN*4]; //sum:节点值, optv:加法标记, optmul:乘法标记 
    inline void pushup(int o) { sumv[o]=sumv[rson]+sumv[lson]; return; }
    inline void pushdown(int o, int l, int r)
    {
        if(optv[o]==0 && optmul[o]==1) return;
        int mid = (l+r)>>1;
        sumv[rson] = sumv[rson] * optmul[o] + optv[o] * (r-mid);
        sumv[lson] = sumv[lson] * optmul[o] + optv[o] * (mid-l+1);
        sumv[rson] %=p; sumv[lson]%=p;
        //给左右子节点赋值 
        optv[lson]*=optmul[o]; optv[rson]*=optmul[o];
        optv[lson]+=optv[o]; optv[rson]+=optv[o];
        optmul[lson]*=optmul[o]%p; optmul[rson]*=optmul[o]%p;
        optv[lson]%=p; optv[rson]%=p; optmul[lson]%=p; optmul[rson]%=p;
        //下发标记 
        optv[o]=0; optmul[o]=1;
        //清空当前节点的标记 
        //printf("ol:%d, or:%d, optmul:%d, mid:%d, optv:%d\n", l, r, mid, optmul[o], optv[o]);
        //printf("l:%d, r:%d, sum:%d\n", l, mid, sumv[lson]);
        //printf("l:%d, r:%d, sum:%d\n", mid+1, r, sumv[rson]);
    }
    inline void build(int o, int l, int r) //建树 
    {
        optv[o]=0; optmul[o]=1; //标记初始化 
        if(l == r) { sumv[o]=a[l]; return; }
        int mid = (l+r) >>1;
        build(lson, l, mid);
        build(rson, mid+1, r);
        pushup(o);
    }
    inline LL querysum(int o, int l, int r, int ql, int qr) //查询 
    {
        if(l>=ql && r<=qr) return sumv[o];
        pushdown(o, l, r);
        LL ans =0; 
        int mid = (l+r) >>1;
        if(mid>=ql) ans+= querysum(lson, l, mid, ql, qr);
        if(mid+1<=qr) ans+= querysum(rson, mid+1, r, ql, qr);
        pushup(o); 
        //printf("[querysum] l:%d, r:%d, sum:%d\n", l, r, sumv[o]);
        //printf("return:%d\n", ans);
        return ans%p;
    }
    inline void optadd(int o, int l, int r, int ql, int qr, int v, int type) //添加标记 
    {
        if(l>=ql && r<=qr)
        {
            if(type==2) //添加加法标记 
            {
                optv[o]+=v;
                sumv[o]+=(v*(r-l+1));
                sumv[o]%=p; 
            }
            if(type==1) //添加乘法标记 
            {
                optmul[o]*=v%p;
                optv[o]*=v%p;
                sumv[o]*=v%p;
                sumv[o]%=p;
            }
            //printf("l:%d, r:%d, sum:%d, optv:%d, optmul:%d\n", l, r, sumv[o], optv[o], optmul[o]);
            return;
        }
        pushdown(o, l, r);
        int mid = (l+r) >>1;
        if(mid>=ql) optadd(lson, l, mid, ql, qr, v, type);
        if(mid+1<=qr) optadd(rson, mid+1, r, ql, qr, v, type);
        pushup(o);
        //printf("[optadd] l:%d, r:%d, sum:%d\n", l, r, sumv[o]);
    }
} st;
int main()
{
    scanf("%d%d%d", &n, &m, &p);
    for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
    st.build(1, 1, n);
    //for(int i=1; i<=2*n; i++) printf("%lld ", st.sumv[i]); printf("\n");
    for(int i=1; i<=m; i++)
    {
        int tmp;
        scanf("%d", &tmp);
        if(tmp==3)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            printf("%d\n", st.querysum(1, 1, n, x, y)%p);
        }
        else
        {
            int x, y, k;
            scanf("%d%d%d", &x, &y, &k);
            st.optadd(1, 1, n, x, y, k, tmp);
        }
        //printf("\n");
    }
    return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...