cogs 1272. [AHOI2009] 行星序列


★★★   输入文件:seqb.in   输出文件:seqb.out   简单对比
时间限制:2 s   内存限制:1280 MB
【题目描述】


“神州“载人飞船的发射成功让小可可非常激动,他立志长大后要成为一名宇航员假期一始,他就报名参加了“小小宇航员夏令营”,在这里小可可不仅学到了丰富的宇航知识,还参与解决了一些模拟飞行中发现的问题,今天指导老师交给他一个任务,在这次模拟飞行的路线上有N个行星,暂且称它们为一个行星序列,并将他们从1至n标号,在宇宙未知力量的作用下这N个行星的质量是不断变化的,所以他们对飞船产生的引力也会不断变化,小可可的任务就是在飞行途中计算这个行星序列中某段行星的质量和,以便能及时修正飞船的飞行线路,最终到达目的地,行星序列质量变化有两种形式:
1,行星序列中某一段行星的质量全部乘以一个值
2,行星序列中某一段行星的质量全部加上一个值
由于行星的质量和很大,所以求出某段行星的质量和后只要输出这个值模P的结果即可,小可可被这个任务难住了,聪明的你能够帮他完成这个任务吗?

【输入格式】


第一行两个整数N和P(1<=p<=1000000000);
  第二行含有N个非负整数,从左到右依次为a1,a2,…………,an(0<=ai<。1000000001<=i<=n),其中ai表示第i个行星的质量:
  第三行有一个整数m,表示模拟行星质量变化以及求质量和等操作的总次数。从第四行开始每行描述一个操作,输入的操作有以下三种形式:
   操作1:1 t g c 表示把所有满足t<=i<=g的行星质量ai改为ai*c
   操作2:2 t g c 表示把所有满足t<=i<=g的行星质量ai改为ai+c
   操作3:3 t g 表示输出所有满足t<=i<=g的ai的和模p的值
   其中:1<=t<=g<=N,0<=c<=10000000
   注:同一行相邻的两数之间用一个空格隔开,每行开头和末尾没有多余空格

【输出格式】

对每个操作3,按照它在输入中出现的顺序,依次一行输出一个整数表示所求行星质量和
【样例输入】

7 43
1 2 3 4 5 6 7 
5
1 2 5 5 
3 2 4
2 3 7 9
3 1 3 
3 4 7
【样例输出】

2
35
8
【提示】


100%的数据中,M,N<=100000
40%的数据中,M,N<=10000

【来源】

AHOI2009
调了两个小时,还是没调出来,看题解 双懒惰标记
#include<iostream>
#include<cstdio>

using namespace std;

int mod;
struct data {
	long long add,mul,sum;
	int l,r;
} tree[400001];

inline int read()
{
	int x=0;int f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
	return x*f;
}

void init(int jd,int l,int r) 
{
	tree[jd].l=l;
	tree[jd].r=r;
	tree[jd].add=0;//will 加 
	tree[jd].mul=1;//will 乘 
	tree[jd].sum=0;//区间值 
	if(l==r)return;
	init(jd*2,l,(l+r)/2);
	init(jd*2+1,(l+r)/2+1,r);
}

void up(int jd) 
{
	tree[jd].sum=(tree[jd*2].sum+tree[jd*2+1].sum)%mod;
}

void down(int jd) 
{
	if(tree[jd].add==0&&tree[jd].mul==1)return;
	tree[jd*2].mul=(tree[jd*2].mul*tree[jd].mul)%mod;
	tree[jd*2].add=(tree[jd*2].add*tree[jd].mul+tree[jd].add)%mod;
	tree[jd*2].sum=(tree[jd*2].sum*tree[jd].mul+(tree[jd*2].r-tree[jd*2].l+1)*tree[jd].add)%mod;
	tree[jd*2+1].mul=(tree[jd*2+1].mul*tree[jd].mul)%mod;
	tree[jd*2+1].add=(tree[jd*2+1].add*tree[jd].mul+tree[jd].add)%mod;
	tree[jd*2+1].sum=(tree[jd*2+1].sum*tree[jd].mul+(tree[jd*2+1].r-tree[jd*2+1].l+1)*tree[jd].add)%mod;
	tree[jd].add=0;
	tree[jd].mul=1;
}

void _add(int jd,int l,int r,long long add,long long mul)
{
	if(tree[jd].l>=l&&tree[jd].r<=r) 
	{
		tree[jd].mul=(tree[jd].mul*mul)%mod;
		tree[jd].add=(tree[jd].add*mul+add)%mod;
		tree[jd].sum=(tree[jd].sum*mul+(tree[jd].r-tree[jd].l+1)*add)%mod;
		return;
	}
	down(jd);
	int mid=(tree[jd].l+tree[jd].r)/2;
	if(r<=mid)_add(jd*2,l,r,add,mul);
	else if(l>mid)_add(jd*2+1,l,r,add,mul);
	else _add(jd*2,l,mid,add,mul),_add(jd*2+1,mid+1,r,add,mul);
	up(jd);
}

long long query(int jd,int l,int r) 
{
	if(tree[jd].l>=l&&tree[jd].r<=r)return tree[jd].sum;
	down(jd);
	int mid=(tree[jd].l+tree[jd].r)/2;
	if(r<=mid)return query(jd*2,l,r);
	else if(l>mid)return query(jd*2+1,l,r);
	else return (query(jd*2,l,mid)+query(jd*2+1,mid+1,r))%mod;
}

int main() 
{
	freopen("seqb.in","r",stdin);
	freopen("seqb.out","w",stdout);
	int n,m;
	n=read(),mod=read();
	init(1,1,n);
	for(int i=1; i<=n; i++) 
	{
		int g;
		g=read();
		_add(1,i,i,g,1);
	}
	m=read();
	for(int i=1; i<=m; i++) 
	{
		int a,b,c,d;
		a=read(),b=read(),c=read();
		if(a!=3)d=read();
		if(a==1)_add(1,b,c,0,d);//乘
		if(a==2)_add(1,b,c,d,1);//加
		if(a==3)printf("%d\n",query(1,b,c));
	}
	return 0;
}
/*
7 43
1 2 3 4 5 6 7 
5
1 2 5 5 
3 2 4
2 3 7 9
3 1 3 
3 4 7
*/

  

posted @ 2017-07-21 09:55  ioioioioioio  阅读(243)  评论(0编辑  收藏  举报