废了……求助!给解决方案

2. 线段树2

题目ID:7337必做题100分

最新提交:

Wrong Answer

0 分

历史最高:

Wrong Answer

0 分

时间限制: 1000ms

空间限制: 524288kB

题目描述

如题,已知一个数列,你需要进行下面三种操作:

  • 将某区间每一个数乘上 x
  • 将某区间每一个数加上 x
  • 求出某区间每一个数的和

输入格式:

第一行包含三个整数 n,m,p,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含 n 个用空格分隔的整数,其中第 i 个数字表示数列第 i 项的初始值。

接下来 m 行每行包含若干个整数,表示一个操作,具体如下:

操作 1: 格式:1 x y k 含义:将区间 [x,y] 内每个数乘上 k

操作 2: 格式:2 x y k 含义:将区间 [x,y] 内每个数加上 k

操作 3: 格式:3 x y 含义:输出区间 [x,y] 内每个数的和对 p 取模所得的结果

样例:

输入:

5 5 38 1 5 4 2 3 2 1 4 1 3 2 5 1 2 4 2 2 3 5 5 3 1 4

输出:

17 2

数据规模:

对于 30% 的数据:n≤103,m≤104
对于 100% 的数据:n≤105,m≤105,p=571373 k≤1e18。

RE:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int MAX_N=1e6+10;
const int MX=100;
const ll BASE=131;
const ll MOD=10000000007;
const int mxN=84;
const int mxK=14;
const int MAXSIZE=300;
ll n,m,z[MAX_N];
typedef struct ST{
    ll ans[MAX_N],sum[MAX_N],add[MAX_N]={0},p;
    inline ll lch(ll a){return (a<<1);}
    inline ll rsh(ll a){return (a<<1|1);}
    inline void pushdown(ll a,ll l,ll r){
        ll mid=(l+r)>>1;
        ll ls=lch(a),rs=rsh(a);
        ans[ls]=(ans[ls]*sum[a]%p+add[a]*(mid-l+1)%p)%p;
        ans[rs]=(ans[rs]*sum[a]%p+add[a]*(r-mid)%p)%p;
        sum[ls]=(sum[ls]*sum[a])%p;
        sum[rs]=(sum[rs]*sum[a])%p;
        add[ls]=(add[ls]*sum[a]%p+add[a])%p;
        add[rs]=(add[rs]*sum[a]%p+add[a])%p;
        sum[a]=1;
        add[a]=0;
        return;
    }
    inline void building(ll a,ll l,ll r,ll *v){
        if(l==r){ans[a]=v[l]%p;}
        else{
            ll mid=(l+r)>>1;
            biuding(lch(a),l,mid,v);
            biuding(rsh(a),mid+1,r,v);
            ans[a]=(ans[lch(a)]+ans[rsh(a)])%p;
        }
        return;
    }
    inline void toUP(ll tl,ll tr,ll l,ll r,ll a,ll b,bool type){
        if(tl<=l&&r<=tr){
            if(type){
                ans[a]=b*ans[a]%p;
                sum[a]=sum[a]*b%p;
                add[a]=add[a]*b%p;
            }else{
                ans[a]=(ans[a]+b*(r-l+1))%p;
                add[a]=(add[a]+b)%p;
            }
            return;
        }
        pushdown(a,l,r);
        ll mid=(l+r)>>1;
        if(tl<=mid)toUP(tl,tr,l,mid,lch(a),b,type);
        if(tr>mid)toUP(tl,tr,mid+1,r,rsh(a),b,type);
        ans[a]=(ans[lch(a)]+ans[rsh(a)])%p;
        return;
    }
    inline ll range(ll tl,ll tr,ll l,ll r,ll a){
        ll cnt=0;
        if(tl<=l&&r<=tr)return ans[a]%p;
        ll mid=(l+r)>>1;
        pushdown(a,l,r);
        if(tl<=mid)cnt+=range(tl,tr,l,mid,lch(a))%p;
        if(tr>mid)cnt+=range(tl,tr,mid+1,r,rsh(a))%p;
        return cnt%p;
    } 
}ST;
ST st;
int main(){
    cin>>n>>m>>st.p;
    memset(st.sum,1,sizeof(st.sum));
    ll a,l,r,k;
    for(ll i=1;i<=n;i++)cin>>z[i];
    st.building(1,1,n,z);
    for(ll i=0;i<m;i++){
        cin>>a>>l>>r;
        if(a==1){
            cin>>k;
            st.toUP(1,1,n,l,r,k,1);
        }else if(a==2){
            cin>>k;
            st.toUP(1,1,n,l,r,k%st.p,0);
        }else{
            printf("%lld\n",st.range(1,1,n,l,r)%st.p);
        }
    }
    return 0;
}

你好,我花点时间调一下

强,线段树我不精通
但是我精通看RE的位置,可以用gdb,

调线段树我都快调疯了,所以我是蒟蒻

建议使用分块(

老师叫我们用线段树

漂亮,样例可以RE

building拼错了让人忍俊不禁(

image
自己体悟

为什么前面有*

我想写

而且这不会RE

你这a有问题啊(
image

a?

第84行调用是不是和58行有点冲突,我看l和r没对上

好像就是 toUP 的参数没写对

a越来越大(*2
image
image
image
image

image
@LeuR 也可能是range的问题
@向耕立 退出的条件一直没达到:
image

@向耕立 调一下试试,我帮你看运行

以及 a=1 时的 k 也要 %p 吧

我看看