题目链接: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. VisualStudio一打开工程就崩溃-重打开output显示We were unable to automatically populate your Visual Studio Online accounts.

    and this method exactly effected on me

  2. SQLServer 本地移动发布/订阅/分发数据库文件并更改逻辑名称和物理文件名

    -------------------------------------------------------------------------------------------------- - ...

  3. JVM性能监控工具-Jvisualvm

    用法:Jvisualvm是JDK自带的一款性能分析工具 使用方式: 1.配置好JDK环境变量 1.本地JVM监控略 2.远程JVM监控 用JMX对Resin内存状态进行监控 ,可以看到本地所有可监控的 ...

  4. Android学习系列(43)--使用事件总线框架EventBus和Otto

    事件总线框架 针对事件提供统一订阅,发布以达到组件间通信的解决方案. 原理 观察者模式. EventBus和Otto 先看EventBus的官方定义: Android optimized event ...

  5. 2016.9.14 JavaScript入门之七面向对象和函数

    1.JavaScript中的变量,可以是对象,具有相应的属性: 2.我们也能够使用构造函数创建对象.构造函数的函数给出了一个大写的名称,以使它清楚地表明它是一个构造函数. 在构造函数中,这个变量是指由 ...

  6. mybaties 的一些点

    resultMap resutType mybaties缓存 待续 mybaties对应关系是bean和数据库字段的对应. 1.mybaties 的返回值是对象的话定义为resultMap=" ...

  7. 读取Excel数据到Table表中

    方法一: try { List<DBUtility.CommandInfo> list = new List<DBUtility.CommandInfo>(); string ...

  8. 优先队列 UVA 11997 K Smallest Sums

    题目传送门 题意:训练指南P189 分析:完全参考书上的思路,k^k的表弄成有序表: 表1:A1 + B1 <= A1 + B2 <= .... A1 + Bk 表2:A2 + B1 &l ...

  9. ZOJ3195 Design the city(LCA)

    题目大概说给一棵树,每次询问三个点,问要把三个点连在一起的最少边权和是多少. 分几种情况..三个点LCA都相同,三个点有两对的LCA是某一点,三个点有两对的LCA各不相同...%……¥…… 画画图可以 ...

  10. Colorado Potato Beetle(CF的某道) & 鬼畜宽搜

    题意: 一个人在一张大图上走,给你路径与起点,求他走出的矩形面积并.(大概这个意思自行百度标题... SOL: 与其说这是一道图论题不如说是一道生动活泼的STL-vector教学.... 离散化宽搜, ...