luogu P3373 【模板】线段树 2
题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.将某区间每一个数乘上x
3.求出某区间每一个数的和
输入输出格式
输入格式:
第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k
操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k
操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果
输出格式:
输出包含若干行整数,即为所有操作3的结果。
输入输出样例
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
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^)
样例说明:

故输出应为17、2(40 mod 38=2)
需要越来越习惯lazy-tag的使用才行啊
tag1表示乘,tag2表示加
线段树的写法真是各有各的风格 大雾
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; typedef long long ll; inline int read(){
char ch;
int re=;
bool flag=;
while((ch=getchar())!='-'&&(ch<''||ch>''));
ch=='-'?flag=:re=ch-'';
while((ch=getchar())>=''&&ch<='') re=re*+ch-'';
return flag?-re:re;
} struct segment{
int l,r;
ll sum,tag1,tag2;
segment(){
sum=;
tag1=;
tag2=;
}
}; const int maxn=; int cnt,n,m;
ll mod;
segment tre[maxn<<];
int data[maxn]; inline void push_up(int x){
tre[x].sum=(tre[x<<].sum+tre[x<<|].sum)%mod;
} void build(int x,int l,int r){
tre[x].l=l; tre[x].r=r;
if(l==r){
tre[x].sum=data[l];
return;
}
int mid=(l+r)>>;
build(x<<,l,mid); build(x<<|,mid+,r);
push_up(x);
} void init(){
n=read(); m=read(); mod=read();
for(int i=;i<=n;i++) data[i]=read();
build(,,n);
} inline void push_down(int x){
int lson=x<<,rson=lson|; if(tre[x].tag1!=){
tre[lson].tag1=(tre[lson].tag1*tre[x].tag1)%mod;
tre[rson].tag1=(tre[rson].tag1*tre[x].tag1)%mod;
tre[lson].tag2=(tre[lson].tag2*tre[x].tag1)%mod;
tre[rson].tag2=(tre[rson].tag2*tre[x].tag1)%mod;
tre[lson].sum=(tre[lson].sum*tre[x].tag1)%mod;
tre[rson].sum=(tre[rson].sum*tre[x].tag1)%mod;
tre[x].tag1=;
} if(tre[x].tag2){
tre[lson].tag2=(tre[lson].tag2+tre[x].tag2)%mod;
tre[lson].sum=(tre[lson].sum+tre[x].tag2*(tre[lson].r-tre[lson].l+))%mod;
tre[rson].tag2=(tre[rson].tag2+tre[x].tag2)%mod;
tre[rson].sum=(tre[rson].sum+tre[x].tag2*(tre[rson].r-tre[rson].l+))%mod;
tre[x].tag2=;
}
} void update_add(int x,int L,int R,int c){
if(L<=tre[x].l&&tre[x].r<=R){
tre[x].tag2=(tre[x].tag2+c)%mod;
tre[x].sum=(tre[x].sum+c*(tre[x].r-tre[x].l+))%mod;
return;
} int mid=(tre[x].l+tre[x].r)>>;
if(tre[x].tag1!=||tre[x].tag2) push_down(x);
if(R<=mid) update_add(x<<,L,R,c);
else if(L>mid) update_add(x<<|,L,R,c);
else{ update_add(x<<,L,mid,c); update_add(x<<|,mid+,R,c); }
push_up(x);
} void update_mul(int x,int L,int R,int c){
if(L<=tre[x].l&&tre[x].r<=R){
tre[x].tag1=(tre[x].tag1*c)%mod;
tre[x].tag2=(tre[x].tag2*c)%mod;
tre[x].sum=(tre[x].sum*c)%mod;
return;
} int mid=(tre[x].l+tre[x].r)>>;
if(tre[x].tag1!=||tre[x].tag2) push_down(x);
if(R<=mid) update_mul(x<<,L,R,c);
else if(L>mid) update_mul(x<<|,L,R,c);
else{ update_mul(x<<,L,mid,c); update_mul(x<<|,mid+,R,c); }
push_up(x);
} ll query_sum(int x,int L,int R){
if(L<=tre[x].l&&tre[x].r<=R){
return tre[x].sum;
}
if(tre[x].tag1!=||tre[x].tag2) push_down(x);
int mid=(tre[x].l+tre[x].r)>>;
if(R<=mid) return query_sum(x<<,L,R);
if(L>mid) return query_sum(x<<|,L,R);
return (query_sum(x<<,L,mid)+query_sum(x<<|,mid+,R))%mod;
} void solve(){
int opt,L,R,c;
for(int i=;i<m;i++){
opt=read();
switch(opt){
case :{
L=read(); R=read(); c=read();
update_mul(,L,R,c);
break;
}
case :{
L=read(); R=read(); c=read();
update_add(,L,R,c);
break;
}
case :{
L=read(); R=read();
printf("%lld\n",query_sum(,L,R));
break;
}
}
}
} int main(){
//freopen("temp.in","r",stdin);
init();
solve();
return ;
}
她的话不多但笑起来是那么平静优雅
她柔弱的眼神里装的是什么 是思念的忧伤
luogu P3373 【模板】线段树 2的更多相关文章
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- hdu 1754 I Hate It (模板线段树)
http://acm.hdu.edu.cn/showproblem.php?pid=1754 I Hate It Time Limit: 9000/3000 MS (Java/Others) M ...
- hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询
点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...
- 【线段树】【P3372】模板-线段树
百度百科 Definition&Solution 线段树是一种log级别的树形结构,可以处理区间修改以及区间查询问题.期望情况下,复杂度为O(nlogn). 核心思想见百度百科,线段树即将每个 ...
- [Luogu] 可持久化线段树 1(主席树)
https://www.luogu.org/problemnew/show/P3834 #include<cstdio> #include<iostream> #include ...
- 算法模板——线段树6(二维线段树:区域加法+区域求和)(求助phile)
实现功能——对于一个N×M的方格,1:输入一个区域,将此区域全部值作加法:2:输入一个区域,求此区域全部值的和 其实和一维线段树同理,只是不知道为什么速度比想象的慢那么多,求解释...@acphile ...
- Luogu P5280 [ZJOI2019]线段树
送我退役的神题,但不得不说是ZJOIDay1最可做的一题了 先说一下考场的ZZ想法以及出来后YY的优化版吧 首先发现每次操作其实就是统计出增加的节点个数(原来的不会消失) 所以我们只要统计出线段树上每 ...
- luogu 1712 区间(线段树+尺取法)
题意:给出n个区间,求选择一些区间,使得一个点被覆盖的次数超过m次,最小的花费.花费指的是选择的区间中最大长度减去最小长度. 坐标值这么大,n比较小,显然需要离散化,需要一个技巧,把区间转化为半开半闭 ...
- Luogu P3960 列队 线段树
题面 线段树入门题. 我们考虑线段树来维护这个矩阵. 首先我们先定n+1棵线段树前n棵维护每行前m-1个同学中没有离队过的同学,还有一棵维护第m列中没有离队过的同学.再定n+1棵线段树前n棵线段树维护 ...
- Luogu P1471 方差 线段树
那是上上周...也是重构了四遍...后来GG了...今天又拾起,搞了搞终于过了... 好吧就是个线段树,公式懒得推了https://www.cnblogs.com/Jackpei/p/10693561 ...
随机推荐
- 《孵化twitter》读书笔记
寒假在家看完了第一本书——<孵化twitter:从蛮荒到IPO的狂野旅程>.在2014上半年,尝试看了该书的英文原版,奈何自己英语太菜,实在看不懂.这次有了中文版,就决定要看看.该书对于我 ...
- Android计时器实现
Wyy.java package com.test; import android.app.Activity;import android.app.Service;import android.os. ...
- (文件)图片上传,Spring或SpringMVC框架
spring或springMVC框架图片(文件)上传 页面部分,用一个简单的form表单提交文件,将图片或文件提交到服务端.一个输入框,用于输入图片的最终名称,一个file文件选择,用于选择图片. 页 ...
- datagrid 添加、修改、删除(转载)
原链接:JQueryEasyUI学习笔记(十)datagrid 添加.修改.删除 基于datagrid框架的删除.添加与修改: 主要是批量删除,双击表单修改.选中行修改,增加行修改,再有就是扩展edi ...
- 反射型XSS的逆袭之路
0×00背景 这是一次结合各自技巧的渗透过程,由于原作者的截图不多,我们只是简单叙述一下思路~ 目标是一家本地的游戏公司,起因是找到一个反射型xss,但是却被对方公司忽略,而作者身边的一个妹子也在这家 ...
- angular.js的ng-app 指令定义一个 AngularJS 应用程序。
<!DOCTYPE html> <html lang="en" ng-app> <head> <meta charset="UT ...
- 去除MyEclipse频繁弹出的Update Progress窗口
方法1: 1.关闭updating index Window => Preferences => Myeclipse Enterprise Workbench => Maven4My ...
- Web直接导入导出SHP/CAD实现探讨。
1.导入SHP/CAD文件 WEB具有直接美观展现功能,功能实现到可视化最好不要超过3S,那么就要限制导入文件的大小和优化算法了. 1.1.SHP导入实现思路 SHP格式开源,Git上随便可以找到读取 ...
- 【LeetCode】112. Path Sum
题目: Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up ...
- 怎么用VBS脚本自动注册yy娱乐的账号
set WshShell=WScript.CreateObject("WScript.Shell") Const user = "hugetech2" Cons ...