Yuanfang is puzzled with the question below: 
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(线段树——懒惰标记的妙用)的更多相关文章

  1. K - Transformation HDU - 4578 线段树经典题(好题)

    题意:区间  加   变成定值 乘  区间查询:和 平方和 立方和 思路:超级超级超级麻烦的一道题  设3个Lazy 标记分别为  change 改变mul乘 add加  优先度change>m ...

  2. hdu 4578 线段树(标记处理)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others) ...

  3. 【HDU】4092 Nice boat(多校第四场1006) ——线段树 懒惰标记

    Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) To ...

  4. HDU 4578 线段树玄学算法?

    Transformation 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4578 Problem Description Yuanfang is p ...

  5. Codeforces 444C 线段树 懒惰标记

    前天晚上的CF比赛div2的E题,很明显一个线段树,当时还在犹豫复杂度的问题,因为他是区间修改和区间查询,肯定是要用到懒惰标记. 然后昨天真的是给这道题跪了,写了好久好久,...我本来是写了个add标 ...

  6. HDU 4578 线段树复杂题

    题目大意: 题意:有一个序列,有四种操作: 1:区间[l,r]内的数全部加c. 2:区间[l,r]内的数全部乘c. 3:区间[l,r]内的数全部初始为c. 4:询问区间[l,r]内所有数的P次方之和. ...

  7. HDU - 4578 线段树+三重操作

    这道题自己写了很久,还是没写出来,也看了很多题解,感觉多数还是看的迷迷糊糊,最后面看到一篇大佬的才感觉恍然大悟. 先上一篇大佬的题解:https://blog.csdn.net/aqa20372995 ...

  8. hdu 4578 线段树 ****

    链接:点我  1

  9. hdu 3954 线段树 (标记)

    Level up Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

随机推荐

  1. Discuz ML! V3.X 代码注入漏洞

    Discuz ML! V3.X 代码注入漏洞 前言 Discuz!ML是一个由CodersClub.org创建的多语言,集成,功能齐全的开源网络平台,用于构建像"社交网络"这样的互 ...

  2. Linux文件权限设置教程

    Linux的文件基本权限有9个,分别是owenr.group.others三种身份各自有自己的r.w和x,比如"rwxrwxrwx",就表示owener具有r.w.x权限,同样gr ...

  3. Spring_AOP基于AspectJ的注解开发&JDBC的模板使用&事务管理(学习笔记3)

    一:AOP基于AspectJ的注解开发 1,简单的实例: 1)引入相应的jar包 ​ 2)在配置文件里引入相关约束 <beans xmlns="http://www.springfra ...

  4. vijos P1848 记数问题

    自答[119ms内存456.0 KiB] #include<iostream>using namespace std;int num = 0;void judge(int n, int x ...

  5. 2017day1

    http://www.cnblogs.com/alex3714/articles/5465198.html 四.Python安装 windows 1 2 3 4 5 6 7 1.下载安装包     h ...

  6. mysql查看视图用户

    select `DEFINER` from  information_schema.VIEWS;

  7. linux初学者-文件的归档和传输

      1.文件归档 因为linux系统都是以文件的形式存在,所以在处理文件时有时候因为文件太多导致传输速度慢等问题,为了提高方便并且提高效率,常把文件归档,文件归档就是把多个文件变成一个归档文件. 文件 ...

  8. linux初学者-输出输入管理

      1.输出重定向 在linux中,因为用户的权限不同,所以访问某些文件或者目录会被拒绝而形成错误输出,这些错误的输出也会显示出来.一般正确输出的编号为1,错误输出的编号为2.如下图,在普通用户stu ...

  9. JAVA-1.连接数据库

    import java.sql.*; import com.mysql.jdbc.Driver; /* * <JDBC基础篇> * 连接数据库一般来说分为6个步骤: *1-加载驱动 *2- ...

  10. Spring MVC中的 权限拦截定义 以及 权限拦截的研发步骤

    权限拦截 (拦截器: 对请求进行区分) 1 实现的价值(作用) 用户未登录:访问没用登录的URL,拦截到以后 跳转回登录 用户未登录:访问登录的URL,直接放行到后续流程处理框架,进行后续的操作 用户 ...