记录编号 57331 评测结果 AAAAAAAAAA
题目名称 [AHOI2009] 行星序列 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 3.960 s
提交时间 2013-04-09 15:31:15 内存使用 8.71 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iomanip>
using namespace std;
long long MOD;
long long d[100001]={0};//每个点的值
int n;
int tot=0;
class SEGMENT{
public:
	int l,r;//区间
	int lchild,rchild;//两个子节点的静态指针
	long long s;//区间和
	long long inc,mul;//附加的,没有往下加的标记
	void change(long long c,long long m);
	void build(int left,int right);
}tree[200001];
#define now tree[root]
void SEGMENT::build(int left,int right){
	l=left,r=right,inc=0,mul=1;
	if(left<right){
		int mid=(left+right)>>1;
		lchild=++tot;
		tree[tot].build(left,mid);
		rchild=++tot;
		tree[tot].build(mid+1,right);
		s=(tree[lchild].s+tree[rchild].s)%MOD;
	}
	else{
		s=d[left]%MOD;
		lchild=rchild=-1;
	}
}
void SEGMENT::change(long long c,long long m){//乘m加c
	s*=m,s%=MOD;
	s+=(r-l+1)*c,s%=MOD;
	mul*=m,mul%=MOD;
	inc*=m,inc%=MOD;
	inc+=c,inc%=MOD;
}
void add(int root,int x,int y,long long c,long long m,long long pc,long long pm){
	if(root==-1) return;
	now.change(pc,pm);
	if(now.r<x||now.l>y) return;
	if(x<=now.l&&now.r<=y){//包含这个节点
		now.change(c,m);
		return;
	}
	else{
		add(now.lchild,x,y,c,m,now.inc,now.mul);
		add(now.rchild,x,y,c,m,now.inc,now.mul);
		now.inc=0,now.mul=1;
		now.s=(tree[now.lchild].s+tree[now.rchild].s)%MOD;
	}
}
long long getsum(int root,int x,int y,long long pc,long long pm){
	if(root==-1) return 0;
	now.change(pc,pm);
	if(now.r<x||now.l>y) return 0;
	if(x<=now.l&&now.r<=y){
		return now.s;
	}
	else{
		long long x1,x2;
		x1=getsum(now.lchild,x,y,now.inc,now.mul);
		x2=getsum(now.rchild,x,y,now.inc,now.mul);
		now.inc=0,now.mul=1;
		now.s=(tree[now.lchild].s+tree[now.rchild].s)%MOD;
		return (x1+x2)%MOD;
	}
}
int main(){
	freopen("seqb.in","r",stdin);
	freopen("seqb.out","w",stdout);
	cin>>n>>MOD;
	for(int i=1;i<=n;i++) cin>>d[i],d[i]%=MOD;
	tree[tot].build(1,n);
	int m;
	scanf("%d",&m);
	int temp;
	long long k;
	int lnow,rnow;
	for(int i=0;i<m;i++){
		scanf("%d",&temp);
		if(temp==1){
			scanf("%d%d",&lnow,&rnow);
			cin>>k;
			add(0,lnow,rnow,0,k%MOD,0,1);
		}
		else if(temp==2){
			scanf("%d%d",&lnow,&rnow);
			cin>>k;
			add(0,lnow,rnow,k%MOD,1,0,1);
		}
		else{
			scanf("%d%d",&lnow,&rnow);
			cout<<getsum(0,lnow,rnow,0,1)<<endl;
		}
	}
	return 0;
}