题目描述 Description

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

1,行星序列中某一段行星的质量全部乘以一个值

2,行星序列中某一段行星的质量全部加上一个值

由于行星的质量和很大,所以求出某段行星的质量和后只要输出这个值模P的结果即可,小可可被这个任务难住了,聪明的你能够帮他完成这个任务吗?

输入描述 Input Description

第一行两个整数N和P(1<=p<=1000000000);

第二行含有N个非负整数,从左到右依次为a1,a2,…………,an(0<=ai<=100000000,1<=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

注:同一行相邻的两数之间用一个空格隔开,每行开头和末尾没有多余空格

输出描述 Output Description

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

样例输入 Sample Input
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
样例输出 Sample Output
2
35
8
数据范围及提示 Data Size & Hint

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

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

题意:中文题面,对一段序列的三种操作,重点是更新操作有两种

某个区间的数都增加c或者都乘以c

题解: 此题注意开long long

如果是单个更新操作的话,就是很容易的区间延迟标记,但是如果是两种不同的操作呢,这样是会有冲突的,

也就是对于一个下放区间的标记是先处理乘法呢?还是先处理加法呢?

参考了别人的代码之后,我是这样理解的,乘法的标记只对某个区间的sum值起作用,并且对于乘法标记的下放,

不仅要更新下放区间的plu,还要将plu转换为add

也可以这样考虑,就某一个数无非两种标记的执行顺序不同导致结果不同

先加后乘(add+sum)*plu=sum*plu+add*plu;

先乘后加sum*plu+add=sum*plu+add*1;

观察一下如何使得两种情况一起处理呢?就是把add*plu转化为新的add

具体看代码;

 /******************************
code by drizzle
blog: www.cnblogs.com/hsd-/
^ ^ ^ ^
O O
******************************/
//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<algorithm>
#include<cmath>
#define ll long long
#define PI acos(-1.0)
#define mod 1000000007
using namespace std;
struct node
{
int l,r;
ll sum;
ll add;
ll plu;
} tree[];
int n;
ll p;
int q;
int exm;
int l1,r1;
ll cc;
void build(int root,int left,int right)
{
tree[root].l=left;
tree[root].r=right;
tree[root].add=;
tree[root].plu=;
if(left==right)
{
tree[root].sum=;
scanf("%lld",&tree[root].sum);
tree[root].sum%=p;
return ;
}
int mid=(left+right)>>;
build(root<<,left,mid);
build(root<<|,mid+,right);
tree[root].sum=(tree[root<<].sum+tree[root<<|].sum)%p;
}
void pushdown(int root)
{
if(tree[root].l==tree[root].r) return ;
ll pl=tree[root].plu;//针对区间sum起作用
ll ad=tree[root].add;
tree[root<<].sum=(tree[root<<].sum*pl%p+(tree[root<<].r-tree[root<<].l+)*ad%p)%p;
tree[root<<|].sum=(tree[root<<|].sum*pl%p+(tree[root<<|].r-tree[root<<|].l+)*ad%p)%p;
tree[root<<].add=(tree[root<<].add*pl+ad)%p;//对于这个区间的每个元素将plu转化为了add
tree[root<<|].add=(tree[root<<|].add*pl+ad)%p;
tree[root<<].plu=(tree[root<<].plu*pl)%p;
tree[root<<|].plu=(tree[root<<|].plu*pl)%p;
tree[root].add=;
tree[root].plu=;
}
void updata(int root,int left,int right,ll c,int flag)
{
pushdown(root);
if(tree[root].l==left&&tree[root].r==right)
{
if(flag==)
{
tree[root].plu=(tree[root].plu*c)%p;
tree[root].sum=tree[root].sum*c%p;
return ;
}
if(flag==)
{
tree[root].add=(tree[root].add+c)%p;
tree[root].sum=(tree[root].sum+c*(right-left+))%p;
return ;
}
}
int mid=(tree[root].l+tree[root].r)>>;
if(right<=mid)
updata(root<<,left,right,c,flag);
else
{
if(left>mid)
updata(root<<|,left,right,c,flag);
else
{
updata(root<<,left,mid,c,flag);
updata(root<<|,mid+,right,c,flag);
}
}
tree[root].sum=(tree[root<<].sum+tree[root<<|].sum)%p;
}
ll query(int root,int left,int right)
{
pushdown(root);
if(tree[root].l==left&&tree[root].r==right)
{
return tree[root].sum;
}
int mid=(tree[root].l+tree[root].r)>>;
if(right<=mid)
return query(root<<,left,right);
else
{
if(left>mid)
return query(root<<|,left,right);
else
return query(root<<,left,mid)+query(root<<|,mid+,right);
}
}
int main()
{
while(~scanf("%d %lld",&n,&p))
{
build(,,n);
scanf("%d",&q);
for(int i=; i<=q; i++)
{
scanf("%d",&exm);
if(exm==)
{
scanf("%d %d %lld",&l1,&r1,&cc);
updata(,l1,r1,cc,);
}
if(exm==)
{
scanf("%d %d %lld",&l1,&r1,&cc);
updata(,l1,r1,cc,);
}
if(exm==)
{
scanf("%d %d",&l1,&r1);
printf("%lld\n",query(,l1,r1)%p);
}
}
}
return ;
}

codevs 2216 线段树 两种更新方式的冲突的更多相关文章

  1. 关于使用lazytag的线段树两种查询方式的比较研究

    说到线段树,想来大家并不陌生——最基本的思路就是将其规划成块,然后只要每次修改时维护一下即可. 但是尤其是涉及到区间修改时,lazytag的使用往往能够对于程序的质量起到决定性作用(Ex:一般JSOI ...

  2. POJ 3225 线段树区间更新(两种更新方式)

    http://blog.csdn.net/niuox/article/details/9664487 这道题明显是线段树,根据题意可以知道: (用0和1表示是否包含区间,-1表示该区间内既有包含又有不 ...

  3. ZOJ-1610 线段树+两种查询方法(弥补我线段树区间填充的短板)

    ZOJ-1610 线段树+两种查询方法(弥补我线段树区间填充的短板) 题意 题意:给一个n,代表n次操作,接下来每次操作表示把[l,r]区间的线段涂成k的颜色其中,l,r,k的范围都是0到8000 这 ...

  4. POJ 2299-Ultra-QuickSort-线段树的两种建树方式

    此题有两种建树方式! Description In this problem, you have to analyze a particular sorting algorithm. The algo ...

  5. codevs 1080 线段树点修改

    先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...

  6. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  7. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  8. ACM: Copying Data 线段树-成段更新-解题报告

    Copying Data Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Description W ...

  9. hdu1754线段树的单点更新区间查询

    I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

随机推荐

  1. Delphi out 参数 string Integer

    http://www.delphibasics.co.uk/RTL.asp?Name=Out http://stackoverflow.com/questions/14507310/whats-the ...

  2. IT公司100题-21-输入n和m,和等于m

    问题描述: 输入两个整数n 和m,从数列1,2,3,…,n 中随意取几个数, 使其和等于m,将所有可能的组合都打印出来.   分析: 利用递归的思路,对于1,2,3,…,n 中的任意一个数,要么选,要 ...

  3. IT公司100题-18-圆圈中最后剩下的数字

    问题描述: n个数字(下标为0, 1, …, n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(当前数字从1开始计数).当一个数字被删除后,从被删除数字的下一个数字开始计数,继续删除 ...

  4. English test for certificate

    <英语口译全真试题精解> GPA 3.5 (MTI)  (CPA) ( GRE )  1350分+3.5以上 SAT ( TOEFL )  100分以上 TOEIC BEC (剑桥商务英语 ...

  5. S5PV210之添加缺少的-内核提供的'.h'文件 linux3.0.8驱动

    怎样解决编译时出现内核提供的函数或变量没有定义,使用source insight搜索功能找到声明的头文件,然后包含该头件就行了: 比如: error: implicit declaration of ...

  6. php中的include()的使用技巧

    php中的include()的使用技巧 include() 语句包括并运行指定文件. 以下文档也适用于 require().这两种结构除了在如何处理失败之外完全一样.include() 产生一个警告而 ...

  7. NTP服务器的配置

    安装cloudera Manager的时候,必须要求集群的主机之间时间同步,搭建一个NTP服务器的思路是,首先通过一台主机master与外网进行时间同步,然后其他的slaver主机与主机master进 ...

  8. GSM Hacking:使用BladeRF、树莓派、YatesBTS搭建便携式GSM基站

    每次看到黑客在网上发布的那些GSM技术相关文章我都十分惊讶.然而在没有Software Defined Radios (SDRs)之前,玩GSM并不便宜,除此之外想要好好玩你得下大功夫. 拓展阅读 G ...

  9. 【LeetCode OJ】Reverse Words in a String

    Problem link: http://oj.leetcode.com/problems/reverse-words-in-a-string/ Given an input string, reve ...

  10. iOS:Size Classes的使用

    iOS 8在应用界面的可视化设计上添加了一个新的特性-Size Classes,对于任何设备来说,界面的宽度和高度都只分为两种描述:正常和紧凑.这样开发者便可以无视设备具体的尺寸,而是对这两类和它们的 ...