【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 ...
随机推荐
- UML九种图详解-外链
http://blog.csdn.net/fanxiaobin577328725/article/details/51591482
- ie上如何兼容placeholder
首先,判断浏览器是否支持placeholder属性: var input = document.createElement('input'); if("placeholder" i ...
- 【hibernate merge】session1.merge(T entity)方法的含义和update方法的区别
注意: MERGE语句是SQL语句的一种.在SQL Server.Oracle数据库中可用,MySQL.PostgreSQL中不可用. 1>session1.merge(T entity) 合 ...
- Android 使用 LruCache 缓存图片
在你应用程序的 UI 界面加载一张图片是一件很简单的事情,但是当你需要在界面上加载一大堆图片的时候,情况就变得复杂起来.在很多情况下,(比如使用 ListView, GridView 或者 ViewP ...
- 20145223《Java程序设计》第6周学习总结
20145223 <Java程序设计>第6周学习总结 教材学习内容总结 ·Java中将数据从来源取出或是将数据写入目的地,使用输入.输出串流,其分别的代表对象为java.io.InputS ...
- 表格边框css
table标签默认是没有边框的,但是如果我们自己加上边框boder:1px solid black;只有整个表格最外面有边框,那么如何给表格添加样式使得整个表格的tr.td都具有边框呢: <st ...
- linux(centos6)搭建ftp服务器
前提 ssh服务已经开启,关闭防火墙,主机和虚拟机能ping通 查看ssh和防火墙的状态 service sshd status service iptables status 开启ssh服务 ser ...
- 简单的实现UIpicker上面的取消确定按钮
1 因为我用的xib实现的添加picker 和textfiled的, @interface ViewController : UIViewController<UITextFieldDelega ...
- 【原】iOS学习41之多线程
1. 多线程概述 1> 程序.进程和进程的概念 程序:由源代码生成的可执行应用.(例如:QQ.app) 进程:一个正在运行的程序可以看做一个进程.(例如:正在运行的QQ就是一个进程),进程拥有独 ...
- soapui中文操作手册(一)----创建一个新的项目
1) 创建一个新的项目 点击项目,选择新建项目SOAP.这将打开一个新的SOAP项目对话框. 注意:你也可以做CTRL + N(WIN)或CMD+ N(MAC)来创建一个新的SOAP项目. 在新的SO ...