题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578

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

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

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

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

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

思路:比较复杂的线段树操作。只有一个询问操作,那就是询问[l,r]之间数的p次方之和,我们不可能全部查询的节点,会TLE,最好的情况就是查询到一段[a,b],这段区间内所有的值都相等,那么返回(b-a+1)*val 的值即可。 根据询问操作我们即可意识到我们要维护的是区间内所有值都相同的情况的区间。对于覆盖和加乘操作,我开始以为向下传递两层即可,这样是错误的,因为即可传递下去两层,还是有可能同时存在加乘操作。所以我们可以分两种情况讨论:1、当为覆盖操作时,直接覆盖区间即可,并且把标记的加乘操作赋为初始值。2、当为加乘操作时,先判断当前区间段是否为相同的值,是的话直接加乘,维护这个相同的值即可。如果不相同,看区间是否已有加乘标记,把这个加乘标记一直传递下去,知道遇见那个区间段区间所有值的相同停止。最后把这个加乘赋给最开始的区间段。简单的说就是,覆盖操作可直接维护,不是覆盖操作的话,区间只能保留一个加乘操作。

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std; #define lz 2*u,l,mid
#define rz 2*u+1,mid+1,r
typedef long long lld;
const int maxn=;
const int mod=;
lld add[*maxn], mul[*maxn], ch[*maxn], sum[*maxn]; void build(int u, int l, int r)
{
mul[u]=;
add[u]=sum[u]=;
ch[u]=;
if(l==r)
{
ch[u]=;
return ;
}
int mid=(l+r)>>;
build(lz);
build(rz);
} void push_down(int u, int l, int r)
{
if(l==r) return ;
int mid=(l+r)>>;
if(ch[u])
{
add[*u]=, mul[*u]=;
add[*u+]=, mul[*u+]=;
ch[*u]=ch[*u+]=;
sum[*u]=sum[*u+]=sum[u];
ch[u]=;
}
else
{
if(add[u])
{
if(ch[*u]) sum[*u]=(sum[*u]+add[u])%mod;
else
{
push_down(lz);
add[*u]=(add[*u]+add[u])%mod;
}
if(ch[*u+]) sum[*u+]=(sum[*u+]+add[u])%mod;
else
{
push_down(rz);
add[*u+]=(add[*u+]+add[u])%mod;
}
add[u]=;
}
if(mul[u]>)
{
if(ch[*u]) sum[*u]=(sum[*u]*mul[u])%mod;
else
{
push_down(lz);
mul[*u]=(mul[*u]*mul[u])%mod;
}
if(ch[*u+]) sum[*u+]=(sum[*u+]*mul[u])%mod;
else
{
push_down(rz);
mul[*u+]=(mul[*u+]*mul[u])%mod;
}
mul[u]=;
}
}
} void Update(int u, int l, int r, int tl, int tr, int c, int op)
{
if(tl<=l&&r<=tr)
{
if(op==)
{
ch[u]=;
mul[u]=, add[u]=;
sum[u]=c;
}
else
{
if(ch[u])
{
if(op==) sum[u]=(sum[u]+c)%mod;
else sum[u]=sum[u]*c%mod;
}
else
{
push_down(u,l,r);
if(op==) add[u]=(add[u]+c)%mod;
else mul[u]=mul[u]*c%mod;
}
}
return ;
}
push_down(u,l,r);
int mid=(l+r)>>;
if(tr<=mid) Update(lz,tl,tr,c,op);
else if(tl>mid) Update(rz,tl,tr,c,op);
else
{
Update(lz,tl,mid,c,op);
Update(rz,mid+,tr,c,op);
}
} lld Query(int u, int l, int r, int tl, int tr, int p)
{
if(tl<=l&&r<=tr)
{
if(ch[u])
{
lld ans=, tp=sum[u];
for(int i=; i<=p; i++) ans=ans*tp%mod;
return (r-l+)*ans%mod;
}
}
push_down(u,l,r);
int mid=(l+r)>>;
if(tr<=mid) return Query(lz,tl,tr,p);
else if(tl>mid) return Query(rz,tl,tr,p);
else
{
lld t1=Query(lz,tl,mid,p);
lld t2=Query(rz,mid+,tr,p);
return (t1+t2)%mod;
}
} int main()
{
int n, m;
while(cin >> n >> m, n+m)
{
build(,,n);
for(int i=; i<=m; i++)
{
int l, r, c, op;
scanf("%d%d%d%d",&op,&l,&r,&c);
if(op<=) Update(,,n,l,r,c,op);
else printf("%I64d\n",Query(,,n,l,r,c)%mod);
}
}
return ;
}

【HDU4578 Transformation】线段树的更多相关文章

  1. HDU4578 Transformation 线段树

    这个题让我重新学习了加 乘 在区间的操作 题解:http://blog.csdn.net/guognib/article/details/25324025?utm_source=tuicool& ...

  2. 30-Transformation(HDU4578)-区间线段树(复杂)

    http://acm.hdu.edu.cn/showproblem.php?pid=4578 Transformation Time Limit: 15000/8000 MS (Java/Others ...

  3. Transformation 线段树好题 好题 (独立写出来对线段树不容易)

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

  4. HDU 4578 Transformation --线段树,好题

    题意: 给一个序列,初始全为0,然后有4种操作: 1. 给区间[L,R]所有值+c 2.给区间[L,R]所有值乘c 3.设置区间[L,R]所有值为c 4.查询[L,R]的p次方和(1<=p< ...

  5. hdu 4578 Transformation 线段树

    没什么说的裸线段树,注意细节就好了!!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> ...

  6. hdu 4578 Transformation 线段树多种操作裸题

    自己写了一个带结构体的WA了7.8次 但是测了几组小数据都对..感觉问题应该出在模运算那里.写完这波题解去对拍一下. 以后线段树绝不写struct!一般的struct都带上l,r 但是一条线段的长度确 ...

  7. HDU-4578 Transformation(线段树的多种区间操作)

    http://acm.hdu.edu.cn/showproblem.php?pid=4578 Time Limit: 15000/8000 MS (Java/Others)    Memory Lim ...

  8. HDU - 4578 Transformation(线段树区间修改)

    https://cn.vjudge.net/problem/HDU-4578 题意 4种操作,区间加,区间乘,区间变为一个数,求区间的和.平方和以及立方和. 分析 明显线段树,不过很麻烦..看kuan ...

  9. HDU 4578 - Transformation - [加强版线段树]

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

随机推荐

  1. sql 提取数字、字母、汉字

    --提取数字 IF OBJECT_ID('DBO.GET_NUMBER2') IS NOT NULL DROP FUNCTION DBO.GET_NUMBER2 GO )) ) AS BEGIN BE ...

  2. java基本数据类型及相互间的转换

    1.首先复习一下java的基本数据类型,见下图 2.比较他们的字节数 备注:1字节(Byte)=8位(Bit) 3.转换中的知识点 *java中整数类型默认的int类型:小数类型默认的double: ...

  3. Action处理请求参数

    第一种 :Action 本身作为model对象,通过成员setter封装 (属性驱动 ) 第一种方式:<br> <form action="${pageContext.re ...

  4. Linux IO模型和网络编程模型

    术语概念描述: IO有内存IO.网络IO和磁盘IO三种,通常我们说的IO指的是后两者. 阻塞和非阻塞,是函数/方法的实现方式,即在数据就绪之前是立刻返回还是等待. 以文件IO为例,一个IO读过程是文件 ...

  5. SpringMVC解析5-DispatcherServlet逻辑细节

    MultipartContent类型的request处理 对于请求的处理,spring首先考虑的是对于Multipart的处理,如果是MultipartContent类型的request,则转换req ...

  6. 有损FLV视频的画面宽高比修改方案

    问题背景: 需要向网站上发布一条视频新闻,就是新闻只有一段视频.上面给的是一个FLV的视频,大小接近200M,差不多200分钟吧.本来觉得很简单的事,直接上传发布就完了,但是一波三折啊……第一轮上传时 ...

  7. 泛型容器单元(Generics.Collections)[3]: TStack<T> 堆栈列表

    TQueue 和 TStack, 一个是队列列表, 一个是堆栈列表; 一个是先进先出, 一个是先进后出. TStack 主要有三个方法.一个属性:Push(压栈).Pop(出栈).Peek(查看下一个 ...

  8. 转:delphi异常捕获try except语句 和 try finally语句用法

    转:http://www.java123.net/v/936977.html      2015-06-24 09:27:48 一直写程序都没管他们,也尽量很少用,今天终于想把他给弄个明白,在网上找来 ...

  9. ajax 异步交互

    <script>     $(function(){         $("#sub").click(function () {             $.ajax( ...

  10. BZOJ3898 : 打的士

    设$f_i$表示选择的答案区间左端点为$i$时,区间长度最小是多少. 那么每来一批人的时候,设$nxt$为$i$右边最近的一个可行决策,则$f_i=\max(f_i,nxt-i)$. 注意到$f$的形 ...