题目大意:

题意:有一个序列,有四种操作:

1:区间[l,r]内的数全部加c。

2:区间[l,r]内的数全部乘c。

3:区间[l,r]内的数全部初始为c。

4:询问区间[l,r]内所有数的P次方之和。

这里p可以等于1,2,3三种情况,所以我们需要建立3个数组,当然这里其实只用一个sum[4*N][3]的2维数组其实更好

to[],add[],mul[]为三个懒惰标记to[]先于另外两个,每次做完to[],另外两个标记就要将其初始化

对于mul[]来说,每次执行,add[cur]*=mul[cur]也要随之增加

因为这道题目数过大,需要求mod 10007的值

因为这个我把代码从上午看到了下午简直要疯了

int最大值2147483647

你必须每执行一步操作都需要mod一次,*2后,10007*2*10007 int还不至于爆掉,但也差不多

但是若*3之后那肯定要是再碰到一个超大数,那就GG了

所以每次乘法算完都mod一次吧,每次做mod带上括号是一个好习惯~~

 //这鬼题目里面最好每执行一次乘法就mod一次,不然可能int要爆掉导致报错,尤其是我在fun_add()中改错改了一天才发现是这个原因
#include <cstdio>
#include <cstring>
using namespace std;
#define N 100005
#define mod 10007
int sum[*N][],add[*N],to[*N],mul[*N];
void update(int cur)
{
sum[cur][]=(sum[cur<<][]+sum[cur<<|][])%mod;
sum[cur][]=(sum[cur<<][]+sum[cur<<|][])%mod;
sum[cur][]=(sum[cur<<][]+sum[cur<<|][])%mod;
}
void build(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
add[cur]=,to[cur]=,mul[cur]=;
if(x==y){
sum[cur][]=sum[cur][]=sum[cur][]=;
return;
}
build(ls,x,mid);
build(rs,mid+,y);
update(cur);
}
void fun_mul(int cur,int x,int y,int val)
{
mul[cur]*=val;
mul[cur]%=mod;
add[cur]*=val;
add[cur]%=mod; int t1=val*val%mod;
int t2=t1*val%mod;
sum[cur][]=sum[cur][]*val;
sum[cur][]%=mod; sum[cur][]=sum[cur][]*t1;
sum[cur][]%=mod; sum[cur][]=sum[cur][]*t2;
sum[cur][]%=mod;
}
void fun_add(int cur,int x,int y,int val)
{
add[cur]+=val;
add[cur]%=mod;
int t1=sum[cur][];
int t2=sum[cur][];
int tmp1=val*val%mod;
int tmp2=val*tmp1%mod;
sum[cur][]+=(y-x+)*val;
sum[cur][]%=mod; sum[cur][]+=(y-x+)*tmp1%mod+((*val)%mod)*t1%mod;
sum[cur][]%=mod; sum[cur][]+=((*val)%mod)*t2%mod+*tmp1*t1%mod+(y-x+)*tmp2%mod;
sum[cur][]%=mod;
}
void fun_to(int cur,int x,int y,int val)
{
mul[cur]=,add[cur]=,to[cur]=val%mod;
int t1=val*val%mod;
int t2=t1*val%mod;
sum[cur][]=(y-x+)*val%mod;
sum[cur][]=(y-x+)*t1%mod;
sum[cur][]=(y-x+)*t2%mod;
}
void pushdown(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(to[cur]){
//to[ls]=to[rs]=to[cur];
fun_to(ls,x,mid,to[cur]);
fun_to(rs,mid+,y,to[cur]);
to[cur]=;
}
if(mul[cur]>){
//mul[ls]*=mul[cur],mul[rs]*=mul[cur];
fun_mul(ls,x,mid,mul[cur]);
fun_mul(rs,mid+,y,mul[cur]);
mul[cur]=;
}
if(add[cur]){
//add[ls]+=add[cur],add[rs]+=add[cur];
fun_add(ls,x,mid,add[cur]);
fun_add(rs,mid+,y,add[cur]);
add[cur]=;
}
}
void change(int cur,int x,int y,int s,int t,int op,int v)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(x>=s&&y<=t){
if(op==) fun_add(cur,x,y,v);
if(op==) fun_mul(cur,x,y,v);
if(op==) fun_to(cur,x,y,v);
return;
}
pushdown(cur,x,y);
if(mid>=s) change(ls,x,mid,s,t,op,v);
if(mid+<=t) change(rs,mid+,y,s,t,op,v);
update(cur);
}
void query(int cur,int x,int y,int s ,int t,int p,int &ans)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(x>=s&&y<=t){
ans+=sum[cur][p-];
ans%=mod;
return;
}
pushdown(cur,x,y);
if(mid>=s) query(ls,x,mid,s,t,p,ans);
if(mid+<=t) query(rs,mid+,y,s,t,p,ans);
}
int main()
{
int n,m,op,x,y,p;
while(scanf("%d%d",&n,&m),n+m){
build(,,n);
for(int i=;i<m;i++){
scanf("%d%d%d%d",&op,&x,&y,&p);
if(op==){
int ans=;
//printf("%d\n",0);
query(,,n,x,y,p,ans);
printf("%d\n",ans%mod);
}
else change(,,n,x,y,op,p);
}
}
}

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 4578 线段树玄学算法?

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

  4. HDU 4893 线段树裸题

    Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  5. hdu 1754 线段树模板题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 #include <cstdio> #include <cmath> # ...

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

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

  7. hdu 4578 线段树 ****

    链接:点我  1

  8. hdu 1754 线段树 水题 单点更新 区间查询

    I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  9. hdu 1754 I Hate It 线段树基础题

    Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求, ...

随机推荐

  1. [转]C#综合揭秘——细说多线程(上)

    引言 本文主要从线程的基础用法,CLR线程池当中工作者线程与I/O线程的开发,并行操作PLINQ等多个方面介绍多线程的开发. 其中委托的BeginInvoke方法以及回调函数最为常用. 而 I/O线程 ...

  2. 动手实现 Redux(六):Redux 总结

    不知不觉地,到这里大家不仅仅已经掌握了 Redux,而且还自己动手写了一个 Redux.我们从一个非常原始的代码开始,不停地在发现问题.解决问题.优化代码的过程中进行推演,最后把 Redux 模式自己 ...

  3. 后TOS时代的码头数字化生产力

    之前看过一篇文章是,是INFORM的副总裁写的关于以TOS外挂模式提升码头生产效能的文章.文章对外挂模式的总结挺好的,我最近也一直从事这块的工作,以此文梳理一下前面的经验,记录一下自己的感想. TOS ...

  4. layer设置弹出全屏

    //弹出即全屏 var index = layer.open({ type: , content: 'http://www.layui.com', area: ['300px', '195px'], ...

  5. PMP项目管理学习笔记(11)——范围管理之定义范围

    定义范围过程组 定义范围包含将项目分解为团队成员要完成的具体工作之前你需要知道的所有一切. 输入:需求文档.项目章程.组织过程资产 工具:辅助工作室.产品分析.代理方案识别.专家判断 辅助工作室: 与 ...

  6. Android(java)学习笔记156:开源框架post和get方式提交数据(qq登录案例)

    1. 前面提到Http的get/post方式  . HttpClient方式,实际工作的时候不常用到,因为这些方式编写代码是很麻烦的 2. Android应用会经常使用http协议进行传输,网上会有很 ...

  7. params.row[params.column.key] vue h函数 当前单元格 h函数 div 属性 值或数组 render

    params.row[params.column.key] vue h函数 当前单元格 h函数 div 属性 值或数组 render

  8. CAD交互绘制直线(网页版)

    用户可以在CAD控件视区任意位置绘制直线. 主要用到函数说明: _DMxDrawX::DrawLine 绘制一个直线.详细说明如下: 参数 说明 DOUBLE dX1 直线的开始点x坐标 DOUBLE ...

  9. SQL Server数据库的除法默认向下取整,要返回小数的解决方法

    num1; / 1000.0 num2; * 1.0 num3; num4; 结果:

  10. HTML基础(五)表单

    表单的工作原理 简单来说就是客户在浏览器输入信息之后,浏览器将用户在表单中的数据进行打包发送给服务器,服务器接收到之后进行处理,如下图 语法 <form> 表单元素</form> ...