Transformation HDU - 4578(线段树——懒惰标记的妙用)

There are n integers, a 1, a 2, …, a n. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between a x and a y inclusive. In other words, do transformation a k<---a k+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between a x and a y inclusive. In other words, do transformation a k<---a k×c, k = x,x+1,…,y.
Operation 3: Change the numbers between a x and a y to c, inclusive. In other words, do transformation a k<---c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between a x and a y inclusive. In other words, get the result of a x p+a x+1 p+…+a y p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.
InputThere are no more than 10 test cases.
For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
The input ends with 0 0.
OutputFor each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.Sample Input
5 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0
Sample Output
307
7489 分析;本题极其巧妙地运用了线段树懒惰标记的功能,由于本题的特殊性,一开始每个元素都是相等的,而且操作也是对于区间进行的,这就会导致很多相同的元素挨在一起,形成一个个区间,为懒惰标记发挥作用和批量操作创造条件;
flag(懒惰标记)表示该区间的元素是否是相同的,v表示这个区间里面元素的值;
然后再通过合理的pushdown和pushup操作便可以快速的实现对于区间的统计工作。这比网上其他的思路(统计sum1,sum2, sum3.....)快很多。 代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + ;
const int mod = ;
struct node
{
int l, r;
int v;
bool flag;
}t[maxn << ];
int n, m; void pushup(int tar)
{
if (t[tar << ].flag && t[tar << | ].flag && t[tar << ].v == t[tar << | ].v)
t[tar].flag = true, t[tar].v = t[tar << ].v;
else t[tar].flag = false;
} void pushdown(int tar)
{
if (t[tar].flag)
{
t[tar << ].flag = t[tar << | ].flag = true;
t[tar << ].v = t[tar << | ].v = t[tar].v;
t[tar].flag = false;
}
} void build(int l, int r, int tar)
{
t[tar].l = l, t[tar].r = r, t[tar].v = , t[tar].flag = true;
if (l == r) return;
int mid = (l + r) >> ;
build(l, mid, tar << );
build(mid + , r, tar << | );
} void update(int ope, int l, int r, int v, int tar)
{
if (t[tar].l == l && t[tar].r == r && t[tar].flag == true)
{
if (ope == ) t[tar].v += v;
else if (ope == ) t[tar].v *= v;
else t[tar].v = v;
t[tar].v %= mod;
return;
}
pushdown(tar);
int mid = (t[tar].l + t[tar].r) >> ;
if (r <= mid) update(ope, l, r, v, tar << );
else if (l > mid) update(ope, l, r, v, tar << | );
else update(ope, l, mid, v, tar << ), update(ope, mid + , r, v, tar << | );
pushup(tar);
} int query(int l, int r, int v, int tar)
{
if (t[tar].l == l && t[tar].r == r && t[tar].flag == true)
{
int res = ;
for (int i = ; i < v; i++)
res *= t[tar].v, res %= mod;
return res * (t[tar].r - t[tar].l + ) % mod;
}
pushdown(tar);
int mid = (t[tar].l + t[tar].r) >> ;
if (r <= mid) return query(l, r, v, tar << );
else if (l > mid) return query(l, r, v, tar << | );
else return (query(l, mid, v, tar << ) + query(mid + , r, v, tar << | )) % mod;
} int main()
{
int ope, x, y, c; while (cin >> n >> m && n && m)
{
build(, n, );
while (m--)
{
scanf("%d%d%d%d", &ope, &x, &y, &c);
if (ope != )
update(ope, x, y, c, );
else cout << query(x, y, c, ) << endl;
}
}
}
Transformation HDU - 4578(线段树——懒惰标记的妙用)的更多相关文章
- K - Transformation HDU - 4578 线段树经典题(好题)
题意:区间 加 变成定值 乘 区间查询:和 平方和 立方和 思路:超级超级超级麻烦的一道题 设3个Lazy 标记分别为 change 改变mul乘 add加 优先度change>m ...
- hdu 4578 线段树(标记处理)
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others) ...
- 【HDU】4092 Nice boat(多校第四场1006) ——线段树 懒惰标记
Nice boat Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) To ...
- HDU 4578 线段树玄学算法?
Transformation 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4578 Problem Description Yuanfang is p ...
- Codeforces 444C 线段树 懒惰标记
前天晚上的CF比赛div2的E题,很明显一个线段树,当时还在犹豫复杂度的问题,因为他是区间修改和区间查询,肯定是要用到懒惰标记. 然后昨天真的是给这道题跪了,写了好久好久,...我本来是写了个add标 ...
- HDU 4578 线段树复杂题
题目大意: 题意:有一个序列,有四种操作: 1:区间[l,r]内的数全部加c. 2:区间[l,r]内的数全部乘c. 3:区间[l,r]内的数全部初始为c. 4:询问区间[l,r]内所有数的P次方之和. ...
- HDU - 4578 线段树+三重操作
这道题自己写了很久,还是没写出来,也看了很多题解,感觉多数还是看的迷迷糊糊,最后面看到一篇大佬的才感觉恍然大悟. 先上一篇大佬的题解:https://blog.csdn.net/aqa20372995 ...
- hdu 4578 线段树 ****
链接:点我 1
- hdu 3954 线段树 (标记)
Level up Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
随机推荐
- SQL Server 根据日期分组、 根据时间段分组(每三个小时一组)
所用数据表: 一.根据日期分组 1. 使用convert() 函数方式 --根据年月 ),CreatTime,)日期,COUNT(*) 次数,sum(Money)总数 from Orders ),Cr ...
- ElasticStack学习(七):ElasticSearch之Mapping初探
一.Mapping的概念 1.Mapping类似于数据库中的Schema的定义,作用如下: 1)定义索引中的字段的名称: 2)定义字段的数据类型,例如字符串.数字.日期.布尔等: 3)对每个字段进行倒 ...
- 一次线上遇到磁盘IO瓶颈的问题处理
Load average %wa 的含义是等待输入输出的CPU时间百分比 结合iostat命令可以发现磁盘已经在100%满负荷在跑 await:每一个IO请求的处理的平均时间(单位是毫秒).这 ...
- MyBatis从入门到精通:select用法进一步讲解
selectAll:笔记 /* 定义接口方法的返回值的时候,必须注意查询SQL可能返回的结果数量.当 返回值最多只有一个结果的时候,可以将结果返回值定义为SysUser,此时 返回值类型为List&l ...
- 快速掌握mongoDB(三)——mongoDB的索引详解
1 mongoDB索引的管理 本节介绍mongoDB中的索引,熟悉mysql/sqlserver等关系型数据库的小伙伴应该都知道索引对优化数据查询的重要性.我们先简单了解一下索引:索引的本质就是一个排 ...
- 单元测试jest部署
引入jest需安装的基础插件: 基础插件 @babel/core 编译工具核心模块包 @babel/preset-env 编译工具,支持es2015特性的编译打包工具包 babel-jest 对.js ...
- 个人永久性免费-Excel催化剂功能第86波-人工智能之图像OCR文本识别全覆盖
在上一年中,Excel催化剂已经送上一波人工智能系列功能,鉴于部分高端用户的需求,再次给予实现了复杂的图像OCR识别,包含几乎所有日常场景,让公司个人手头的图像非结构化数据瞬间变为可进行结构化处理分析 ...
- Node.js socket 双向通信
使用场景: 聊天室:大量数据常驻交互: 技术栈: Node.js, Vue.js || 原生JS 服务端代码: const app = require('http').createServe ...
- [leetcode] 67. Add Binary (easy)
原题链接 思路: 用一个数保存进制,从后往前不断pop出两个数字和进制数相加,放入返回值中. var addBinary = function(a, b) { var arrA = a.split(' ...
- 清除input的默认样式
input { border: none; outline: none; -webkit-appearance: none; }