洛谷P2023 [AHOI2009]维护序列

区间修改

当我们要修改一个区间时,要保证 \(ax+b\) 的形式,即先乘后加的形式。当将区间乘以一个数 \(k\) 时,原来的区间和为 \(ax+b\) ,乘以 \(k\) 得 \(k(ax+b)=kax+kb\) 。

区间加一个数更加简单,原来的区间和为 \(ax+b\) ,加上一个 \(k\) 为 \(ax+b+k\) ,合并 \(b\) ,\(k\) 得 \(ax+(b+k)\) 。

标记下传

\[a(a'x+b')+b = (aa')\cdot x + (ab'+b)
\]

#include<bits/stdc++.h>

using namespace std;
#define lson l, mid, root << 1
#define rson mid + 1, r, root << 1 | 1 const int maxn = 100005;
long long tree[maxn << 2];
int n, p, q;
struct L{
long long mul, add;
}label[maxn << 2]; inline void pushUp(int root)
{
tree[root] = (tree[root << 1] + tree[root << 1 | 1]) % p;
}
inline void pushDown(int root, int len)
{
if(label[root].add == 0 && label[root].mul == 1) return;
else{
tree[root << 1] = (label[root].mul * tree[root << 1] + label[root].add * (len - (len >> 1))) % p;/***长度划分***/
tree[root << 1 | 1] = (label[root].mul * tree[root << 1 | 1] + label[root].add * (len >> 1)) % p;
label[root << 1].add = (label[root].mul * label[root << 1].add + label[root].add) % p;
label[root << 1 | 1].add = (label[root].mul * label[root << 1 | 1].add + label[root].add) % p;
label[root << 1].mul = (label[root << 1].mul * label[root].mul) % p;
label[root << 1 | 1].mul = (label[root << 1 | 1].mul * label[root].mul) % p;
label[root].add = 0; label[root].mul = 1;
}
}
void build(int l, int r, int root)
{
label[root].add = 0; label[root].mul = 1;
if(l == r){
scanf("%lld", &tree[root]); return;
}
int mid = (l + r) >> 1;
build(lson); build(rson);
pushUp(root);
}
void update(int l, int r, int root, int L, int R, int tag, int c)
{
if(L == l && R == r){
if(tag == 1){
tree[root] = tree[root] * c % p;
label[root].add = label[root].add * c % p;
label[root].mul = label[root].mul * c % p;
}else{
tree[root] = (tree[root] + c * (r - l + 1)) % p;
label[root].add = (label[root].add + c) % p;
}
return;
}
pushDown(root, r - l + 1);
int mid = (l + r) >> 1;
if(L >= mid + 1) update(rson, L, R, tag, c);
else if(R <= mid) update(lson, L, R, tag, c);
else{
update(lson, L, mid, tag, c); update(rson, mid + 1, R, tag, c);
}
pushUp(root);
}
long long query(int l, int r, int root, int L, int R)
{
if(L == l && R == r){
return tree[root] % p;
}
pushDown(root, r - l + 1);
int mid = (l + r) >> 1;
if(L >= mid + 1) return (query(rson, L, R) % p);
else if(R <= mid) return (query(lson, L, R) % p);
else{
return ((query(lson, L, mid) + query(rson, mid + 1, R)) % p);
}
}
int main()
{
scanf("%d%d", &n, &p);
build(1, n, 1);
scanf("%d", &q);
for(int cas = 1; cas <= q; cas++){
int tag, t, g, c;
scanf("%d", &tag);
if(tag == 1){
scanf("%d%d%d", &t, &g, &c);
update(1, n, 1, t, g, 1, c);
}
else if(tag == 2){
scanf("%d%d%d", &t, &g, &c);
update(1, n, 1, t, g, 2, c);
}
else{
scanf("%d%d", &t, &g);
printf("%lld\n", query(1, n, 1, t, g) % p);
}
}
return 0;
}

最新文章

  1. 【读书笔记】iOS-ARC-环境下如何查看引用计数的变化
  2. 再次熟悉jdbc连接mysql
  3. RowDataBound事件
  4. 更简单的跨域解决方案 - CORS
  5. 1303: [CQOI2009]中位数图
  6. JUnit 4 如何正确测试异常
  7. JavaScript--正则表达式(笔记)
  8. js中replace的正则替换
  9. Java阻塞中断和LockSupport
  10. easyui源码翻译1.32--Droppable(放置)
  11. (转)html5 Placeholder属性兼容IE6、7方法
  12. 动态加载JS过程中如何判断JS加载完成
  13. uvalive 2965 Jurassic Remains
  14. python2x和python3的区别
  15. &lt;5&gt;Python的uwsgi web服务器
  16. jsp标签库选择框示例
  17. python中TCP协议中的粘包问题
  18. ImageMagick - 智能的灰度空间(GRAYColorspace)让人窒息
  19. 【jquery隐藏、显示事件and提示callback】【淡入淡出fadeToggle】【滑入滑出slideToggle】【动画animate】【停止动画stop】
  20. element-ui input输入框回车事件

热门文章

  1. Bloom 过滤器
  2. 使用Python的pandas-datareader包下载雅虎财经股价数据
  3. Linux之RedHat7如何更换yum源
  4. 一、Signalr WebApi客服
  5. userdel 删除用户
  6. parted分区的步骤
  7. json与string与map的理解
  8. thinkphp5杂谈--项目架构和模板搭建(view视角)
  9. easygui _1
  10. oracle基本语句(第七章、数据库逻辑对象管理)