线段树2样例过WA0pts求救!!!

4. 线段树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。

一百多行代码:

#include<bits/stdc++.h>
#define ll long long
#define cz1 (pos<<1)
#define cz2 (pos<<1|1)
using namespace std;
const int N=100005;
int n,m,mod;
int a[N];
struct s_tree{
	ll sum,add,mul;
	int l,r;
}s[N*4];

void upd(int pos){
	int kk=cz1;
	int mm=cz2;
	s[pos].sum=(s[kk].sum+s[mm].sum)%mod;
	return;
}

void push_down(int pos){
	int kk=cz1;
	int mm=cz2;
	s[kk].sum=(s[kk].sum*s[pos].mul+s[pos].add*(s[kk].r-s[kk].l+1))%mod;
	s[mm].sum=(s[mm].sum*s[pos].mul+s[pos].add*(s[mm].r-s[mm].l+1))%mod;
	s[kk].mul=(s[kk].mul*s[pos].mul)%mod;
	s[mm].mul=(s[mm].mul*s[pos].mul)%mod;
	s[kk].add=(s[kk].add*s[pos].mul+s[pos].add)%mod;
	s[mm].add=(s[mm].add*s[pos].mul+s[pos].add)%mod;
	s[pos].add=0;
	s[pos].mul=1;
	return; 
}

void bld_tree(int pos,int l,int r){
	s[pos].l=l;
	s[pos].r=r;
	s[pos].mul=1;
	if(l==r){
		s[pos].sum=a[l]%mod;
		return;
	}
	int mid=(l+r)>>1;
	int kk=cz1;
	int mm=cz2;
	bld_tree(kk,l,mid);
	bld_tree(mm,mid+1,r);
	upd(pos);
	return;
}

void cm(int pos,int x,int y,int k){
	if(x<=s[pos].l&&s[pos].r<=y){
		s[pos].add=(s[pos].add*k)%mod;
		s[pos].mul=(s[pos].mul*k)%mod;
		s[pos].sum=(s[pos].sum*k)%mod;
		return;
	}
	push_down(pos);
	int kk=cz1;
	int mm=cz2;
	int mid=(s[pos].l+s[pos].r)>>1;
	if(x<=mid){
		cm(kk,x,y,k);
	}
	if(y>mid){
		cm(mm,x,y,k);
	}
	upd(pos);
	return;
}

void ca(int pos,int x,int y,int k){ //区间加法
	if(x<=s[pos].l&&s[pos].r<=y){
		s[pos].add=(s[pos].add+ k)%mod;
		s[pos].sum=(s[pos].sum+k*(s[pos].r-s[pos].l+1))%mod;
		return;
	}
	push_down(pos);
	int kk=cz1;
	int mm=cz2;
	int mid=(s[pos].l+s[pos].r)>>1;
	if(x<=mid){
		ca(kk,x,y,k);
	}
	if(y>mid){
		ca(mm,x,y,k);
	}
	upd(pos);
	return;
}
ll ask_r(int pos,int x,int y){
	if(x<=s[pos].l&&s[pos].r<=y){
		return s[pos].sum;
	}
	push_down(pos);
	int kk=cz1;
	int mm=cz2;
	ll val=0;
	int mid=(s[pos].l+s[pos].r)>>1;
	if(x<=mid){
		val=(val+ask_r(kk,x,y))%mod;
	}
	if(y>mid){
		val=(val+ask_r(mm,x,y))%mod;
	}
	return val;
}

int main(){
	scanf("%d%d%d",&n,&m,&mod);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	bld_tree(1,1,n);
	for(int i=1;i<=m;i++){
		int cz,x,y;
		scanf("%d%d%d",&cz,&x,&y);
		if(cz==1){
			int k;
			scanf("%d",&k);
			cm(1,x,y,k);
		}
		else if(cz==2){
			int k;
			scanf("%d",&k);
			ca(1,x,y,k);
		}
		else{
			cout<<ask_r(1,x,y)<<endl;
		}
	}
	return 0;
}
/*

*/
2 个赞

你都学线段树了?! :face_in_clouds:

2 个赞

把输入时k %= mod

因为爆long long了

结果没变

#include<bits/stdc++.h>
#define ll long long
#define cz1 (pos<<1)
#define cz2 (pos<<1|1)
using namespace std;
const int N=100005;
int n,m,mod;
int a[N];
struct s_tree{
	ll sum,add,mul;
	int l,r;
}s[N*4];

void upd(int pos){
	int kk=cz1;
	int mm=cz2;
	s[pos].sum=(s[kk].sum+s[mm].sum)%mod;
	return;
}

void push_down(int pos){
	int kk=cz1;
	int mm=cz2;
	s[kk].sum=(s[kk].sum*s[pos].mul+s[pos].add*(s[kk].r-s[kk].l+1))%mod;
	s[mm].sum=(s[mm].sum*s[pos].mul+s[pos].add*(s[mm].r-s[mm].l+1))%mod;
	s[kk].mul=(s[kk].mul*s[pos].mul)%mod;
	s[mm].mul=(s[mm].mul*s[pos].mul)%mod;
	s[kk].add=(s[kk].add*s[pos].mul+s[pos].add)%mod;
	s[mm].add=(s[mm].add*s[pos].mul+s[pos].add)%mod;
	s[pos].add=0;
	s[pos].mul=1;
	return; 
}

void bld_tree(int pos,int l,int r){
	s[pos].l=l;
	s[pos].r=r;
	s[pos].mul=1;
	if(l==r){
		s[pos].sum=a[l]%mod;
		return;
	}
	int mid=(l+r)>>1;
	int kk=cz1;
	int mm=cz2;
	bld_tree(kk,l,mid);
	bld_tree(mm,mid+1,r);
	upd(pos);
	return;
}

void cm(int pos,int x,int y,int k){
	if(x<=s[pos].l&&s[pos].r<=y){
		s[pos].add=(s[pos].add*k)%mod;
		s[pos].mul=(s[pos].mul*k)%mod;
		s[pos].sum=(s[pos].sum*k)%mod;
		return;
	}
	push_down(pos);
	int kk=cz1;
	int mm=cz2;
	int mid=(s[pos].l+s[pos].r)>>1;
	if(x<=mid){
		cm(kk,x,y,k);
	}
	if(y>mid){
		cm(mm,x,y,k);
	}
	upd(pos);
	return;
}

void ca(int pos,int x,int y,int k){ //区间加法
	if(x<=s[pos].l&&s[pos].r<=y){
		s[pos].add=(s[pos].add+ k)%mod;
		s[pos].sum=(s[pos].sum+k*(s[pos].r-s[pos].l+1))%mod;
		return;
	}
	push_down(pos);
	int kk=cz1;
	int mm=cz2;
	int mid=(s[pos].l+s[pos].r)>>1;
	if(x<=mid){
		ca(kk,x,y,k);
	}
	if(y>mid){
		ca(mm,x,y,k);
	}
	upd(pos);
	return;
}
ll ask_r(int pos,int x,int y){
	if(x<=s[pos].l&&s[pos].r<=y){
		return s[pos].sum;
	}
	push_down(pos);
	int kk=cz1;
	int mm=cz2;
	ll val=0;
	int mid=(s[pos].l+s[pos].r)>>1;
	if(x<=mid){
		val=(val+ask_r(kk,x,y))%mod;
	}
	if(y>mid){
		val=(val+ask_r(mm,x,y))%mod;
	}
	return val;
}

int main(){
	scanf("%d%d%d",&n,&m,&mod);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	bld_tree(1,1,n);
	for(int i=1;i<=m;i++){
		int cz,x,y;
		scanf("%d%d%d",&cz,&x,&y);
		if(cz==1){
			int k;
			scanf("%d",&k);
			k%=mod;
			cm(1,x,y,k);
		}
		else if(cz==2){
			int k;
			scanf("%d",&k);
			k%=mod;
			ca(1,x,y,k);
		}
		else{
			cout<<ask_r(1,x,y)<<endl;
		}
	}
	return 0;
}
/*

*/
2 个赞

十年OI一场空,不开long long见祖宗
还有k要先%p

【纯吐槽】出这种数据有什么意义? - 常规 - 信友队论坛

所以到底是%p还是%mod

2 个赞

mod

那我为啥0pts

2 个赞

你读的是n,m,p就模p,你读的是n,m,mod就模mod

一群巨佬%%%

2 个赞

@栗子酱 @2345安全卫士 关贴!

2 个赞

我已解决

2 个赞

啥?这么快?

2 个赞