BZOJ 1798 (线段树||分块)的标记合并
我原来准备做方差的。。
结果发现不会维护两个标记。。
就是操作变成一个 a*x+b ,每次维护a , b 即可
加的时候a=1 ,b=v
乘的时候a=v ,b=0
#include <cstdio>
const long long Maxn=; long long a[Maxn],n,P,l,r,c,m,type;
struct Node
{
long long mul,add,sum,len;
}tree[Maxn<<]; inline void Change(long long o,long long mul,long long add)
{
tree[o].mul=(tree[o].mul*mul)%P;
tree[o].add=(tree[o].add*mul+add)%P;
tree[o].sum=(tree[o].sum*mul+tree[o].len*add)%P;
}
inline void push_down(long long o)
{
Change(o<<,tree[o].mul,tree[o].add);
Change(o<<|,tree[o].mul,tree[o].add);
tree[o].mul=; tree[o].add=;
}
inline void push_up(long long o)
{
tree[o].sum=(tree[o<<].sum+tree[o<<|].sum)%P;
tree[o].len=tree[o<<].len+tree[o<<|].len;
}
void Build(long long o,long long l,long long r)
{
tree[o].mul=; tree[o].add=;
if (l==r) {tree[o].sum=a[l]; tree[o].len=; return;}
long long mid=(l+r)>>;
Build(o<<,l,mid),Build(o<<|,mid+,r);
push_up(o);
}
void Mul(long long o,long long l,long long r,long long p,long long q,long long v)
{
if (l==p && r==q)
{
Change(o,v,);
return;
}
push_down(o);
long long mid=(l+r)>>;
if (q<=mid) Mul(o<<,l,mid,p,q,v);
if (p>=mid+) Mul(o<<|,mid+,r,p,q,v);
if (p<=mid && q>=mid+)
Mul(o<<,l,mid,p,mid,v),Mul(o<<|,mid+,r,mid+,q,v);
push_up(o);
}
void Add(long long o,long long l,long long r,long long p,long long q,long long v)
{
if (l==p && r==q)
{
Change(o,,v);
return;
}
push_down(o);
long long mid=(l+r)>>;
if (q<=mid) Add(o<<,l,mid,p,q,v);
if (p>=mid+) Add(o<<|,mid+,r,p,q,v);
if (p<=mid && q>=mid+)
Add(o<<,l,mid,p,mid,v),Add(o<<|,mid+,r,mid+,q,v);
push_up(o);
}
long long Sum(long long o,long long l,long long r,long long p,long long q)
{
if (l==p && r==q) return tree[o].sum;
long long mid=(l+r)>>;
push_down(o);
if (q<=mid) return Sum(o<<,l,mid,p,q);
if (p>=mid+) return Sum(o<<|,mid+,r,p,q);
if (p<=mid && q>=mid+)
return (Sum(o<<,l,mid,p,mid)+Sum(o<<|,mid+,r,mid+,q))%P;
}
int main()
{
// freopen("c.in","r",stdin);
scanf("%lld%lld",&n,&P);
for (long long i=;i<=n;i++) scanf("%lld",&a[i]);
Build(,,n);
scanf("%lld",&m);
for (long long i=;i<=m;i++)
{
scanf("%lld",&type);
if (type==)
{
scanf("%lld%lld%lld",&l,&r,&c);
Mul(,,n,l,r,c);
}
if (type==)
{
scanf("%lld%lld%lld",&l,&r,&c);
Add(,,n,l,r,c);
}
if (type==)
{
scanf("%lld%lld",&l,&r);
printf("%lld\n",Sum(,,n,l,r));
}
}
return ;
}
线段树
UPD:2016.6.14
突然发现好久没有写过分块了,想到这道可以分块,push_up写成push_down了..
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#define LL long long
using namespace std;
const LL Maxn=;
const LL Inf=0x3f3f3f3f;
LL a[Maxn],n,P,l,r,c,m,type,Block[Maxn];
struct Node
{
LL mul,add,len,sum;
}tree[Maxn]; inline void Change(LL o,LL mul,LL add)
{
tree[o].mul=(tree[o].mul*mul)%P;
tree[o].add=(tree[o].add*mul+add)%P;
tree[o].sum=(tree[o].sum*mul+tree[o].len*add)%P;
}
inline void push_down(LL o)
{
for (;Block[o]==Block[o-];o--);
for (LL i=o;Block[o]==Block[i];i++) a[i]=(a[i]*tree[Block[i]].mul+tree[Block[i]].add)%P;
tree[Block[o]].mul=,tree[Block[o]].add=;
} inline void push_up(LL o)
{
tree[Block[o]].sum=;
for (;Block[o]==Block[o-];o--);
for (LL i=o;Block[o]==Block[i];i++) tree[Block[o]].sum=(tree[Block[o]].sum+a[i])%P;
}
void Mul(LL p,LL q,LL v)
{
if (Block[p]==Block[q])
{
push_down(p);
for (LL i=p;i<=q;i++) a[i]=(a[i]*v)%P;
push_up(p);
return;
}
for (LL i=Block[p]+;i<Block[q];i++) Change(i,v,);
push_down(p),push_down(q);
for (LL i=p;Block[i]==Block[p];i++) a[i]=(a[i]*v)%P;
for (LL i=q;Block[i]==Block[q];i--) a[i]=(a[i]*v)%P;
push_up(p),push_up(q);
} void Add(LL p,LL q,LL v)
{
if (Block[p]==Block[q])
{
push_down(p);
for (LL i=p;i<=q;i++) a[i]=(a[i]+v)%P;
push_up(p);
return;
}
for (LL i=Block[p]+;i<Block[q];i++) Change(i,,v);
push_down(p),push_down(q);
for (LL i=p;Block[i]==Block[p];i++) a[i]=(a[i]+v)%P;
for (LL i=q;Block[i]==Block[q];i--) a[i]=(a[i]+v)%P;
push_up(p),push_up(q);
}
LL Sum(LL p,LL q)
{
LL ret=;
if (Block[p]==Block[q])
{
push_down(p);
for (LL i=p;i<=q;i++) ret=(ret+a[i])%P;
return ret;
}
for (LL i=Block[p]+;i<Block[q];i++) ret=(ret+tree[i].sum)%P;
push_down(p),push_down(q);
for (LL i=p;Block[i]==Block[p];i++) ret=(ret+a[i])%P;
for (LL i=q;Block[i]==Block[q];i--) ret=(ret+a[i])%P;
return ret;
}
int main()
{
scanf("%lld%lld",&n,&P);
for (LL i=;i<=n;i++) scanf("%lld",&a[i]),a[i]%=P;
LL pos=(LL)sqrt(n);
for (LL i=;i<=n;i++) Block[i]=(i-)/pos+;
memset(tree,,sizeof(tree));
for (LL i=;i<=n;i++) tree[Block[i]].len++;
for (LL i=;i<=n;i++) tree[Block[i]].mul=;
for (LL i=;i<=n;i++) tree[Block[i]].sum=(tree[Block[i]].sum+a[i])%P; scanf("%lld",&m);
for (LL i=;i<=m;i++)
{
scanf("%lld",&type);
if (type==)
{
scanf("%lld%lld%lld",&l,&r,&c);
Mul(l,r,c);
}
if (type==)
{
scanf("%lld%lld%lld",&l,&r,&c);
Add(l,r,c);
}
if (type==)
{
scanf("%lld%lld",&l,&r);
printf("%lld\n",Sum(l,r));
}
}
return ;
}
分块
BZOJ 1798 (线段树||分块)的标记合并的更多相关文章
- bzoj 1798 线段树
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 7163 Solved: 2587[Submit ...
- 洛谷 P5897 - [IOI2013]wombats(决策单调性优化 dp+线段树分块)
题面传送门 首先注意到这次行数与列数不同阶,列数只有 \(200\),而行数高达 \(5000\),因此可以考虑以行为下标建线段树,线段树上每个区间 \([l,r]\) 开一个 \(200\times ...
- codeforces Good bye 2016 E 线段树维护dp区间合并
codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...
- SPOJ - GSS1 —— 线段树 (结点信息合并)
题目链接:https://vjudge.net/problem/SPOJ-GSS1 GSS1 - Can you answer these queries I #tree You are given ...
- BZOJ 3110 线段树套线段树
思路: 外围一个权值线段树 里面是个区间线段树 搞一个标记永久化 //By SiriusRen #include <cstdio> #include <cstring> #in ...
- bzoj 3585 mex - 线段树 - 分块 - 莫队算法
Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问 ...
- BZOJ 4756 线段树合并(线段树)
思路: 1.最裸的线段树合并 2. 我们可以观察到子树求一个东西 那我们直接DFS序好了 入队的时候统计一下有多少比他大的 出的时候统计一下 减一下 搞定~ 线段树合并代码: //By SiriusR ...
- BZOJ 2212线段树的合并
借鉴(抄)了一下题解-- 线段树合并的裸题吧- //By SiriusRen #include <cstdio> #include <cstring> #include < ...
- BZOJ 2733 线段树的合并 并查集
思路: 1.线段树合并(nlogn的) 2.splay+启发式合并 线段树合并比较好写 我手懒 //By SiriusRen #include <cstdio> #include < ...
随机推荐
- 20160622001 GridView 删除列 用模板实现删除时提示确认框
GridView在使用CommandField删除时弹出提示框,在.net2005提供的GridView中我们可以直接添加一个 CommandField删除列:<asp:CommandField ...
- 原创开源项目HierarchyViewer for iOS 2.1 Beta新功能介绍
回顾 HierarchyViewer for iOS是我们发布的一个开源项目,采用GPL v3.0协议. HierarchyViewer for iOS可以帮助iOS应用的开发和测试人员,在没有源代码 ...
- iOS 编码规范
Coding Guidelines for Cocoa https://developer.apple.com/library/prerelease/content/documentation/Coc ...
- ArrayList代码示例
package com.shushine.framework.第七章Java标准类库;import java.util.ArrayList;/** * * <p> * 描述该类情况 {@l ...
- GaugeControl 数字时钟,温度计,仪表盘
https://documentation.devexpress.com/#WindowsForms/CustomDocument18217 This topic will guide you thr ...
- java 导出Excel 大数据量,自己经验总结!(二)
在上一次的基础上加上了样式,以及中文列名 package com.tommy.fundation.util; import java.io.OutputStream; import java.util ...
- qq2440启动linux后插入u盘出现usb 1-1: device descriptor read/64, error -110,usb 1-1: device not accepting address 8, error -110
上位机:ubuntu14.04 64bit 下位机:qq2440 交叉编译器:arm-linux-gcc 3.4.1 下位机使用的linux内核版本:kernel2.6.13 1.插入u盘时错误信息如 ...
- [Git] 怎么使用Git让代码回到以前的某个节点
我们可以使某个文件回到以前的某个节点,也可以使整个文件夹下面的文件都回到以前的某个节点,下面只介绍某个文件的,全部的类似. 按步骤操作完成后本地你选中的文件会变成红色,此时的代码还是原来的代码,但是G ...
- #pragma once与 #ifndef的区别
为了避免同一个文件被include多次 1 #ifndef方式2 #pragma once方式 在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别. ...
- 6/14 Sprint2 看板和燃尽图
中间部分还需要改进 小组评分:(团队总分为80) 团队成员: 101丘娟同学:21 107杨晓霞同学:18 108周诗琦同学:22 124陈程同 ...