首页 技术 正文
技术 2022年11月11日
0 收藏 326 点赞 3,961 浏览 3914 个字

模板题目1:https://www.luogu.org/problemnew/show/P3372

懒惰标记讲解:https://www.cnblogs.com/wushengyang/p/11194456.html

这题目只需要用一个懒惰标记,不用考虑顺序。

AC代码:

#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
const int inf = 0x3f3f3f3f;
int dir[][]={{,},{,},{,},{,-},{-,},{-,-},{,-},{-,}};
#define pi acos(-1)
#define me0(s) memset(s,0,sizeof(s))
#define me1(s) memset(s,1,sizeof(s))
#define mef(s) memset(s,-1,sizeof(s))
#define meinf(s) memset(s,inf,sizeof(s))
const int N=;
#define ls rt<<1
#define rs rt<<1|1
ll a[N],sum[N*],lazy[N*];
void push_up(ll rt){
sum[rt]=sum[ls]+sum[rs]; //更新和
}
void push_down(ll m,ll rt){ //m为总区间长度
if(lazy[rt]){ //如果懒惰标记存在
lazy[ls]+=lazy[rt]; //左子树懒惰标记等于其本身加父亲节点的值
lazy[rs]+=lazy[rt];
sum[ls]+=lazy[rt]*(m-(m>>)); //懒惰标记乘个数
sum[rs]+=lazy[rt]*(m>>);
lazy[rt]=;
}
}
void build(ll l,ll r,ll rt){ //建树
lazy[rt]=; //可以建树直接赋值0
if(l==r){
sum[rt]=a[l];
return ;
}
ll m=(l+r)>>;
build(l,m,ls);
build(m+,r,rs);
push_up(rt);
}
void update(ll L,ll R,ll c,ll l,ll r,ll rt){//区间更新[l,r],[L,R]代表总区间
if(l<=L&&r>=R){
lazy[rt]+=c; //更新懒惰标记
sum[rt]+=c*(R-L+); //更新节点存的sum值
return ;
}
push_down(R-L+,rt); //所有的节点都更新一遍lazy标记
ll m=(L+R)>>; //总区间的一半
if(l<=m) update(L,m,c,l,r,ls); //注意这里递归的是总区间为变量
if(r>m) update(m+,R,c,l,r,rs);
push_up(rt);
}
ll query(ll L,ll R,ll l,ll r,ll rt){ //[l,r]区间
if(l<=L&&r>=R) return sum[rt];
push_down(R-L+,rt);
ll m=(L+R)>>; //总区间的一半
ll ans=;
if(l<=m) ans+=query(L,m,l,r,ls); //这个递归的也是总区间变量
if(r>m) ans+=query(m+,R,l,r,rs);
return ans;
}
int main(int argc, char * argv[])
{
std::ios::sync_with_stdio(false);
int n,m;
cin>>n>>m;
for(int i=;i<=n;i++) cin>>a[i];
build(,n,);
while(m--){
ll op,x,y,k;
cin>>op;
if(op==){
cin>>x>>y>>k;
update(,n,k,x,y,);
}
if(op==){
cin>>x>>y;
cout<<query(,n,x,y,)<<endl;
}
}
return ;
}

模板题目2:https://www.luogu.org/problemnew/show/P3373

这道题目由于存在多种区间更改操作,所以懒惰标记之间有关系,比如如果先求加法的话给他加上一个懒惰标记,再做乘法的话以前的懒惰标记加的那一部分也同时需要做一次乘法,这样才能完整。

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
const int inf = 0x3f3f3f3f;
int dir[][]={{,},{,},{,},{,-},{-,},{-,-},{,-},{-,}};
#define pi acos(-1)
#define ls rt<<1
#define rs rt<<1|1
#define me0(s) memset(s,0,sizeof(s))
#define me1(s) memset(s,1,sizeof(s))
#define mef(s) memset(s,-1,sizeof(s))
#define meinf(s) memset(s,inf,sizeof(s))
const int N=;
ll mod;
ll a[N],sum[N*],lazya[N*],lazym[N*]; //lazya存的加的数,lazym存乘
void push_up(int rt){
sum[rt]=(sum[ls]+sum[rs])%mod;
}
void push_down(ll m,ll rt){
lazya[ls]=(lazya[rt]+lazya[ls]*lazym[rt])%mod;//乘法的分配率
lazya[rs]=(lazya[rt]+lazya[rs]*lazym[rt])%mod;
lazym[ls]=(lazym[rt]*lazym[ls])%mod; //懒惰标记直接乘
lazym[rs]=(lazym[rt]*lazym[rs])%mod;
sum[ls]=(lazya[rt]*(m-(m>>))+sum[ls]*lazym[rt])%mod;
sum[rs]=(lazya[rt]*(m>>)+sum[rs]*lazym[rt])%mod;
lazya[rt]=;
lazym[rt]=;
}
void build(ll l,ll r,ll rt){
lazym[rt]=; //初始化乘值
if(l==r){
sum[rt]=a[l];
return ;
}
ll m=(l+r)>>;
build(l,m,ls);
build(m+,r,rs);
push_up(rt);
}
void update_a(ll L,ll R,ll c,ll l,ll r,ll rt){//做加法
if(l<=L&&r>=R){
sum[rt]=(sum[rt]+(R-L+)*c)%mod;
lazya[rt]=(c+lazya[rt])%mod;
return ;
}
push_down(R-L+,rt);
ll m=(L+R)>>;
if(l<=m) update_a(L,m,c,l,r,ls);
if(r>m) update_a(m+,R,c,l,r,rs);
push_up(rt);
}
void update_m(ll L,ll R,ll c,ll l,ll r,ll rt){//做乘法
if(l<=L&&r>=R){
sum[rt]=(sum[rt]*c)%mod;
lazya[rt]=(c*lazya[rt])%mod;
lazym[rt]=(c*lazym[rt])%mod;
return ;
}
push_down(R-L+,rt);
ll m=(L+R)>>;
if(l<=m) update_m(L,m,c,l,r,ls);
if(r>m) update_m(m+,R,c,l,r,rs);
push_up(rt);
}
ll query(ll L,ll R,ll l,ll r,ll rt){
if(l<=L&&r>=R){
return sum[rt];
}
push_down(R-L+,rt);
ll m=(L+R)>>;
ll ans=;
if(l<=m) ans=(ans+query(L,m,l,r,ls))%mod;
if(r>m) ans=(ans+query(m+,R,l,r,rs))%mod;
return ans%mod;
}
int main(int argc, char * argv[])
{
std::ios::sync_with_stdio(false);
ll n,m,x,y,k,op;
cin>>n>>m>>mod;
for(int i=;i<=n;i++) cin>>a[i];
build(,n,);
while(m--){
cin>>op;
if(op==){
cin>>x>>y>>k;
update_m(,n,k,x,y,);
}
if(op==){
cin>>x>>y>>k;
update_a(,n,k,x,y,);
}
if(op==){
cin>>x>>y;
cout<<query(,n,x,y,)<<endl;
}
}
return ;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,918
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,444
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,255
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,069
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,701
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,741