社区讨论
求助大神。。
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 条回复,欢迎继续交流。
正在加载回复...