【BZOJ】【1798】【AHOI2009】Seq维护序列
线段树
属于线段树中级应用吧……
要打两种标记:乘法和加法标记。一开始我想着可以像只有加法标记那样,永不下传,查询的时候依次累加就好了。后来发现不会写……只好每次update的时候……遇到标记!下传!query的时候遇到标记!下传!暴力地来搞……
然后说下下传的细节:先传乘法,后传加法。因为传乘法标记的时候要连sum带add都要一起乘,如果先传add就会多乘……
/**************************************************************
Problem: 1798
User: Tunix
Language: C++
Result: Accepted
Time:3868 ms
Memory:6748 kb
****************************************************************/ //BZOJ 1798
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
//using namespace std;
const int N=;
typedef long long LL;
//#define debug
int n,m,P,a[N];
int mul[N<<],add[N<<],sum[N<<]; void read(int &v){
v=; int sign=; char ch=getchar();
while(ch<'' || ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>='' && ch<=''){ v=v*+ch-''; ch=getchar();}
v*=sign;
}
#define mid (l+r>>1)
#define L (o<<1)
#define R (o<<1|1) void Push_down(int o,int l,int r){
if (mul[o]!=){
add[L]=((LL)add[L]*mul[o])%P; add[R]=((LL)add[R]*mul[o])%P;
mul[L]=((LL)mul[L]*mul[o])%P; mul[R]=((LL)mul[R]*mul[o])%P;
mul[o]=;
}
if (add[o]!=){
add[L]=((LL)add[L]+add[o])%P; add[R]=((LL)add[R]+add[o])%P;
add[o]=;
}
}
void Push_up(int o,int l,int r){
if (l<r) sum[o]=(sum[L]+sum[R])%P; else sum[o]=;
sum[o]=((LL)sum[o]*mul[o]+(LL)add[o]*(r-l+))%P;
}
void build(int o,int l,int r){
if (l==r) add[o]=sum[o]=a[l],mul[o]=;
else{
build(L,l,mid);
build(R,mid+,r);
add[o]=; mul[o]=;
Push_up(o,l,r);
}
}
int ql,qr;
void update_add(int o,int l,int r,int v){
if (ql<=l && qr>=r)
add[o]=((LL)add[o]+v)%P;
else{
if (mul[o]!= || add[o]) Push_down(o,l,r);
if (ql<=mid) update_add(L,l,mid,v); else Push_up(L,l,mid);
if (qr>mid) update_add(R,mid+,r,v); else Push_up(R,mid+,r);
}
Push_up(o,l,r);
}
void update_mul(int o,int l,int r,int v){
if (ql<=l && qr>=r)
mul[o]=((LL)mul[o]*v)%P,add[o]=(LL)add[o]*v%P;
else{
if (mul[o]!= || add[o]) Push_down(o,l,r);
if (ql<=mid) update_mul(L,l,mid,v); else Push_up(L,l,mid);
if (qr>mid) update_mul(R,mid+,r,v); else Push_up(R,mid+,r);
}
Push_up(o,l,r);
}
int sumv;
void query(int o,int l,int r){
if (ql<=l && qr>=r)
sumv=((LL)sumv+sum[o])%P;
else{
if (mul[o]!= || add[o]) {Push_down(o,l,r); Push_up(L,l,mid); Push_up(R,mid+,r);}
if (ql<=mid) query(L,l,mid);
if (qr>mid) query(R,mid+,r);
}
}
int ans[N],cnt=;
int main(){
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
read(n); read(P);
F(i,,n) read(a[i]);
// F(i,1,n) printf("%d ",a[i]);
// printf("\n");
build(,,n); read(m);
// printf("m=%d\n",m);
int c,v;
F(i,,m){
read(c); read(ql); read(qr);
// printf("c=%d\n",c);
switch(c){
case : read(v); update_mul(,,n,v); break;
case : read(v); update_add(,,n,v); break;
case : sumv=; query(,,n); ans[cnt++]=sumv;break;
}
}
rep(i,cnt-) printf("%d\n",ans[i]);
printf("%d",ans[cnt-]);
return ;
}
【BZOJ】【1798】【AHOI2009】Seq维护序列的更多相关文章
- BZOJ 1798: [Ahoi2009]Seq 维护序列seq( 线段树 )
线段树.. 打个 mul , add 的标记就好了.. 这个速度好像还挺快的...( 相比我其他代码 = = ) 好像是#35.. ---------------------------------- ...
- bzoj 1798: [Ahoi2009]Seq 维护序列seq (线段树 ,多重标记下放)
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 7773 Solved: 2792[Submit ...
- bzoj 1798: [Ahoi2009]Seq 维护序列seq 线段树 区间乘法区间加法 区间求和
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeO ...
- Bzoj 1798: [Ahoi2009]Seq 维护序列seq(线段树区间操作)
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小可 ...
- bzoj 1798 [Ahoi2009]Seq 维护序列seq(线段树+传标)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1798 [题意] 给定一个序列,要求提供区间乘/加,以及区间求和的操作 [思路] 线段树 ...
- BZOJ 1798 AHOI2009 Seq 维护序列 线段树
题目大意:维护一个序列,提供三种操作: 1.将区间中每个点的权值乘上一个数 2.将区间中每个点的权值加上一个数 3.求一段区间的和对p取模的值 2631的超^n级弱化版.写2631之前能够拿这个练练手 ...
- bzoj 1798 [Ahoi2009]Seq 维护序列seq
原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1798 线段树区间更新: 1. 区间同同时加上一个数 2. 区间同时乘以一个数 #inclu ...
- bzoj 1798 [Ahoi2009]Seq 维护序列seq ——线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1798 先乘后加,就可给加法标记乘上乘法标记. 注意可能有 *0 的操作,所以 pshd 时不 ...
- BZOJ 1798: [Ahoi2009]Seq 维护序列seq (线段树乘法加法的混合操作)
题目:点击打开链接 大意:一个数组.三个操作.第一种是区间[a,b]每一个数乘乘,另外一种是区间[a,b]每一个数加c,第三种是查询[a,b]区间的和并对p取摸. 两种操作就不能简单的仅仅往下传 ...
- 1798: [Ahoi2009]Seq 维护序列seq
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 2930 Solved: 1087[Submit ...
随机推荐
- Knockout.Js官网学习(数组observable)
前言 如果你要探测和响应一个对象的变化,你应该用observables. 如果你需要探测和响应一个集合对象的变化,你应该用observableArray . 在很多场景下,它都非常有用,比如你要在UI ...
- Git客户端图文详解如何安装配置GitHub操作流程攻略
收藏自 http://www.ihref.com/read-16377.html Git介绍 分布式 : Git版本控制系统是一个分布式的系统, 是用来保存工程源代码历史状态的命令行工具; 保存点 : ...
- hihoCoder-1000-A+B
题目描述:传统的A+B题 使用语言:C 代码: #include <stdio.h> int main(void){ int a,b; while((scanf("%d %d&q ...
- C#调用C++ Dll
现在项目基本都是旁边C++的哥们做好dll扔给我,然后我调用.好久之前晚上down了一份c#调用c++dll的方法,出处早已经遗忘.闲来无事,放上来好了.原作者看到后可以留言,我会把您链接放上的,帮了 ...
- DB2表结构DDL脚本导出
db2look是导出DDL语句脚本的命令,以下是对db2look的一个简单介绍. 语法:db2look -d <数据库名> -e -t <表名> -o <文件名>. ...
- EXCLE中快速插入图片
在excle中怎么快速插入图片呢,一张一张点实在比较麻烦 解决办法: <table><img src="D:\A.png" width="60" ...
- RAP开发入门-搭建RAP开发环境(一)
ps:补充 RAP (Remote Application Platform) 官网地址eclipse.org/rap 1.下载IDE http://www.eclipse.org/downloads ...
- 开发移动app与服务器端session的状态管理与交互
我们进行web开发的时候,一般使用cookie或session来保存用户的登录状态,通过检查cookie或session的数据来验证用户是否具有对某些需要登录的页面的访问权限,这一切都是通过浏览器来完 ...
- .net 的生成操作
生成操作(BuildAction) 属性:BuildAction 属性指示 Visual Studio .NET 在执行生成时对文件执行的操作. BuildAction 可以具有以下几个值之一: 无( ...
- UITabelView 高级(自定义Cell)
自定义一个Cell 当我们要显示复杂数据的时候,例如要做一个扣扣聊天界面,或是新闻列表,系统的行已经不能满足我们的要求,这个时候我们可以通过自定义这个行,让他显示更多复杂结构的样式. 自定义cell就 ...