线段树断了(只有0分)

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;

struct Node{
    int sum,add=0,mul=1;//初始化
    int l,r;//保存区间 
}tree[N*4];//开4倍空间

int n,m,q;//注意:m是模数
int a[N];

void build(int p,int l,int r);
void update(int pos);
void pushdown(int pos);
void do_add(int p,int x,int y,int k);
void do_mul(int p,int x,int y,int k);
int get_sum(int p,int x,int y);
//声明函数

void build(int p,int x,int y){
    tree[p].l=x,tree[p].r=y;
    tree[p].mul=1;// 初始化mul
    if(x==y){//如果区间长度是1,直接返回 
        tree[p].sum=a[x]%m;
        return ;
    }
    
    int mid=(x+y)>>1;//分两边建树
    build((p<<1),x,mid),build((p<<1)|1,mid+1,y);
    update(p);
}

void update(int pos){
    tree[pos].sum=(tree[pos<<1].sum+tree[(pos<<1)|1].sum)%m;
    return ;
}

void do_add(int p,int x,int y,int k){
    if(x<=tree[p].l && tree[p].r<=y){
        tree[p].sum=(tree[p].sum+(tree[p].r-tree[p].l+1)*k)%m;
        //区间和增加
        tree[p].add=(tree[p].add+k)%m;
        //懒标记增加
        return ; 
    }
    
    pushdown(p);//更新懒标记
    int mid=(tree[p].l+tree[p].r)>>1;//左右区间 
    if(x<=mid) do_add(p<<1,x,y,k);
    if(y>mid) do_add((p<<1)|1,x,y,k);
    update(p);
}

void do_mul(int p,int x,int y,int k){
    if(x<=tree[p].l && tree[p].r<=y){
        tree[p].sum=(tree[p].sum*k)%m;
        tree[p].add=(tree[p].add*k)%m;
        tree[p].mul=(tree[p].mul*k)%m;
        return ; 
    }
    
    pushdown(p);//更新懒标记 
    int mid=(tree[p].l+tree[p].r)>>1;//左右区间 
    if(x<=mid) do_mul(p<<1,x,y,k);
    if(y>mid) do_mul((p<<1)|1,x,y,k);
    update(p);    
}

void pushdown(int pos){
    // 先处理乘法标记
    tree[pos<<1].sum=(tree[pos<<1].sum*tree[pos].mul)%m;
    tree[(pos<<1)|1].sum=(tree[(pos<<1)|1].sum*tree[pos].mul)%m;
    
    tree[pos<<1].mul=(tree[pos<<1].mul*tree[pos].mul)%m;
    tree[(pos<<1)|1].mul=(tree[(pos<<1)|1].mul*tree[pos].mul)%m;
    
    tree[pos<<1].add=(tree[pos<<1].add*tree[pos].mul)%m;
    tree[(pos<<1)|1].add=(tree[(pos<<1)|1].add*tree[pos].mul)%m;
    
    // 再处理加法标记
    tree[pos<<1].sum=(tree[pos<<1].sum+tree[pos].add*(tree[pos<<1].r-tree[pos<<1].l+1))%m;
    tree[(pos<<1)|1].sum=(tree[(pos<<1)|1].sum+tree[pos].add*(tree[(pos<<1)|1].r-tree[(pos<<1)|1].l+1))%m;
    
    tree[pos<<1].add=(tree[pos<<1].add+tree[pos].add)%m;
    tree[(pos<<1)|1].add=(tree[(pos<<1)|1].add+tree[pos].add)%m;
    
    tree[pos].add=0,tree[pos].mul=1;//清空 
}

int get_sum(int p,int x,int y){
    if(x<=tree[p].l&&tree[p].r<=y)
        return tree[p].sum;//直接取出答案 
    
    pushdown(p);
    
    int ans=0;
    int mid=(tree[p].l+tree[p].r)>>1;
    if(x<=mid) ans=(ans+get_sum(p<<1,x,y))%m;
    if(y>mid) ans=(ans+get_sum((p<<1)|1,x,y))%m;
    return ans;
}

signed main(){
    cin>>n>>q>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    build(1,1,n);//建树 
    while(q--){
        int t,x,y,k;
        cin>>t;
        if(t==1) cin>>x>>y>>k,do_mul(1,x,y,k);
        else if(t==2) cin>>x>>y>>k,do_add(1,x,y,k);
        else cin>>x>>y,cout<<get_sum(1,x,y)<<endl;
    }
    return 0;
}

image
洛谷能过QWQ

1 个赞

物资桥你好,但是我不会

取模or数据范围?

我懂了

这道题很恶心的,建议看一下 k 的范围

我开long long了啊?

k 要先 % p

        if(t==1) cin>>x>>y>>k,do_mul(1,x,y,k%p);
        else if(t==2) cin>>x>>y>>k,do_add(1,x,y,k%p);
        else cin>>x>>y,cout<<get_sum(1,x,y)<<endl;

但是,我再前面加了k%=m,m相当于p,没有用

@俞天行 大佬帮忙!!

A了

怎么A的?

加取模

我太强了~不愧是我
P.S. xyd 数据第一次比洛谷NB

值得纪念

@我命由我不由天 关贴吧

xyd数据也是好起来了

仅此一次哦

xsl,这题我也被坑过