【HDU4578 Transformation】线段树
题目链接: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】线段树的更多相关文章
- HDU4578 Transformation 线段树
这个题让我重新学习了加 乘 在区间的操作 题解:http://blog.csdn.net/guognib/article/details/25324025?utm_source=tuicool& ...
- 30-Transformation(HDU4578)-区间线段树(复杂)
http://acm.hdu.edu.cn/showproblem.php?pid=4578 Transformation Time Limit: 15000/8000 MS (Java/Others ...
- Transformation 线段树好题 好题 (独立写出来对线段树不容易)
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others)T ...
- HDU 4578 Transformation --线段树,好题
题意: 给一个序列,初始全为0,然后有4种操作: 1. 给区间[L,R]所有值+c 2.给区间[L,R]所有值乘c 3.设置区间[L,R]所有值为c 4.查询[L,R]的p次方和(1<=p< ...
- hdu 4578 Transformation 线段树
没什么说的裸线段树,注意细节就好了!!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> ...
- hdu 4578 Transformation 线段树多种操作裸题
自己写了一个带结构体的WA了7.8次 但是测了几组小数据都对..感觉问题应该出在模运算那里.写完这波题解去对拍一下. 以后线段树绝不写struct!一般的struct都带上l,r 但是一条线段的长度确 ...
- HDU-4578 Transformation(线段树的多种区间操作)
http://acm.hdu.edu.cn/showproblem.php?pid=4578 Time Limit: 15000/8000 MS (Java/Others) Memory Lim ...
- HDU - 4578 Transformation(线段树区间修改)
https://cn.vjudge.net/problem/HDU-4578 题意 4种操作,区间加,区间乘,区间变为一个数,求区间的和.平方和以及立方和. 分析 明显线段树,不过很麻烦..看kuan ...
- HDU 4578 - Transformation - [加强版线段树]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578 Problem Description Yuanfang is puzzled with the ...
随机推荐
- 苹果推送(APNs)ios push小结
把app删除后就推送不成功了,可以看出deviceToken应该是设备+app来一起识别的,重新安装后仍然为同一个 简介 推送服务APNs(Apple Push Notification servic ...
- C# 插件式程序开发
在网上找了下插件式编程的资料,这里自己先借鉴下别人的,同时发现有自己的看法,不过由于本人水平有限,不一定有参考价值,写出来一方面是为了总结自己,以求提高,另一方面也希望各为朋友看到我的不足,给我提出宝 ...
- SpringRMI解析3-RmiServiceExporter逻辑细节
在发布RMI服务的流程中,有几个步骤可能是我们比较关心的. 获取registry 由于底层的封装,获取Registry实例是非常简单的,只需要使用一个函数LocateRegistry.createRe ...
- BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树
[题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...
- [R]R的工作流
最近处理数据时,一直在纠结程序的结构该如何构建,以减少很多简单又很耗时的工作. 刚好把Rob J Hyndman的blog给浏览了一遍,发现一篇2009年的文章,很有启发. 原文: Workflow ...
- 种树 & 乱搞
题意: 在一个(n+1)*(m+1)的网格点上种k棵树,树必须成一条直线,相邻两棵树距离不少于D,求方案数. SOL: 这题吧...巨坑无比,本来我的思路是枚举每一个从(0,0)到(i,j)的矩形,然 ...
- 在ScrollView下加入的组件,不能自动扩展到屏幕高度
ScrollView中的组件设置android:layout_height="fill_parent"不起作用的解决办法 在ScrollView中添加一个android:fillV ...
- ACM: 限时训练题解-Heavy Coins-枚举子集-暴力枚举
Heavy Coins Bahosain has a lot of coins in his pocket. These coins are really heavy, so he always ...
- 洛谷 P1433 吃奶酪 Label:dfs && 剪枝Ex
题目描述 房间里放着n块奶酪.一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在(0,0)点处. 输入输出格式 输入格式: 第一行一个数n (n<=15) 接下来每行2个实数,表示第i块 ...
- 3801. String LD
Description Stringld (left delete) is a function that gets a string and deletes its leftmost charact ...