HDU 5828 Rikka with Sequence (线段树+剪枝优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828
给你n个数,三种操作。操作1是将l到r之间的数都加上x;操作2是将l到r之间的数都开方;操作3是求出l到r之间的和。
操作1和3就不说了,关键是开方操作。
一个一个开方,复杂度太高,无疑会T。所以我们来剪枝一下。
我们可以观察,这里一个数最多开方4,5次(loglogx次)就会到1,所以要是一段区间最大值为1的话,就不需要递归开方下去了。这是一个剪枝。
如果一段区间的数都是一样大小(最大值等于最小值),那么开方的话,值也会相同。所以只要一次开方就好了,而一次开方也相当于减去 x-sqrt(x)。这是剪枝二。
有了两个剪枝,原本是过了... 后来数据加强了,就T了,无奈...
//#pragma comment(linker, "/STACK:102400000, 102400000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
const int N = 1e5 + ;
struct SegTree {
int l, r, mid;
LL sum, lazy, Max, Min;
}T[N << ]; void build(int p, int l, int r) {
int ls = p << , rs = (p << )|;
T[p].l = l, T[p].r = r, T[p].mid = (l + r) >> , T[p].lazy = ;
if(l == r) {
scanf("%lld", &T[p].sum);
T[p].Max = T[p].Min = T[p].sum;
return ;
}
build(ls, l, T[p].mid);
build(rs, T[p].mid + , r);
T[p].sum = (T[ls].sum + T[rs].sum);
T[p].Min = min(T[ls].Min, T[rs].Min);
T[p].Max = max(T[ls].Max, T[rs].Max);
} void update_add(int p, int l, int r, LL val) {
int ls = p << , rs = (p << )|;
if(T[p].l == l && T[p].r == r) {
T[p].Min += val;
T[p].Max += val;
T[p].sum += (r - l + ) * val;
T[p].lazy += val;
return ;
}
if(T[p].lazy) {
T[ls].lazy += T[p].lazy, T[rs].lazy += T[p].lazy;
T[ls].sum += (T[ls].r - T[ls].l + )*T[p].lazy;
T[rs].sum += (T[rs].r - T[rs].l + )*T[p].lazy;
T[ls].Max += T[p].lazy, T[ls].Min += T[p].lazy;
T[rs].Max += T[p].lazy, T[rs].Min += T[p].lazy;
T[p].lazy = ;
}
if(r <= T[p].mid) {
update_add(ls, l, r, val);
}
else if(l > T[p].mid) {
update_add(rs, l, r, val);
}
else {
update_add(ls, l, T[p].mid, val);
update_add(rs, T[p].mid + , r, val);
}
T[p].sum = (T[ls].sum + T[rs].sum);
T[p].Min = min(T[ls].Min, T[rs].Min);
T[p].Max = max(T[ls].Max, T[rs].Max);
} void update(int p, int l, int r) {
if(T[p].Max == ) //最大值为1 就不需要开方了
return ;
int ls = p << , rs = (p << )|;
if(T[p].l == l && T[p].r == r && T[p].Max == T[p].Min) {
LL temp = T[p].Max - (LL)sqrt(T[p].Max*1.0);
T[p].Max -= temp;
T[p].Min -= temp;
T[p].lazy -= temp;
T[p].sum -= (r - l + )*temp;
return ;
}
if(T[p].lazy) {
T[ls].lazy += T[p].lazy, T[rs].lazy += T[p].lazy;
T[ls].sum += (T[ls].r - T[ls].l + )*T[p].lazy;
T[rs].sum += (T[rs].r - T[rs].l + )*T[p].lazy;
T[ls].Max += T[p].lazy, T[ls].Min += T[p].lazy;
T[rs].Max += T[p].lazy, T[rs].Min += T[p].lazy;
T[p].lazy = ;
}
if(r <= T[p].mid) {
update(ls, l, r);
}
else if(l > T[p].mid) {
update(rs, l, r);
}
else {
update(ls, l, T[p].mid);
update(rs, T[p].mid + , r);
}
T[p].sum = (T[ls].sum + T[rs].sum);
T[p].Min = min(T[ls].Min, T[rs].Min);
T[p].Max = max(T[ls].Max, T[rs].Max);
} LL query(int p, int l, int r) {
int ls = p << , rs = (p << )|;
if(T[p].l == l && T[p].r == r) {
return T[p].sum;
}
if(T[p].lazy) {
T[ls].lazy += T[p].lazy, T[rs].lazy += T[p].lazy;
T[ls].sum += (T[ls].r - T[ls].l + )*T[p].lazy;
T[rs].sum += (T[rs].r - T[rs].l + )*T[p].lazy;
T[ls].Max += T[p].lazy, T[ls].Min += T[p].lazy;
T[rs].Max += T[p].lazy, T[rs].Min += T[p].lazy;
T[p].lazy = ;
}
if(r <= T[p].mid) {
return query(ls, l, r);
}
else if(l > T[p].mid) {
return query(rs, l, r);
}
else {
return query(ls, l, T[p].mid) + query(rs, T[p].mid + , r);
}
} int main()
{
int n, m, t, c, l, r;
LL val;
scanf("%d", &t);
while(t--) {
scanf("%d %d", &n, &m);
build(, , n);
while(m--) {
scanf("%d %d %d", &c, &l, &r);
if(c == ) {
scanf("%lld", &val);
update_add(, l, r, val);
}
else if(c == ) {
update(, l, r);
}
else {
printf("%lld\n", query(, l, r));
}
}
}
return ;
}
HDU 5828 Rikka with Sequence (线段树+剪枝优化)的更多相关文章
- hdu 5828 Rikka with Sequence 线段树
Rikka with Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...
- HDU 5828 Rikka with Sequence(线段树区间加开根求和)
Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...
- 2016暑假多校联合---Rikka with Sequence (线段树)
2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...
- 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence
// 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...
- HDU 5828 Rikka with Sequence (线段树)
Rikka with Sequence 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...
- HDU 5828 Rikka with Sequence(线段树 开根号)
Rikka with Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- hdu 4893 Wow! Such Sequence!(线段树)
题目链接:hdu 4983 Wow! Such Sequence! 题目大意:就是三种操作 1 k d, 改动k的为值添加d 2 l r, 查询l到r的区间和 3 l r. 间l到r区间上的所以数变成 ...
- HDU 6089 Rikka with Terrorist (线段树)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6089 题解 这波强行维护搞得我很懵逼... 扫描线,只考虑每个点能走到左上方(不包括正上方,但包括正左 ...
- HDU 5634 Rikka with Phi 线段树
题意:bc round 73 div1 D 中文题面 分析:注意到10^7之内的数最多phi O(log(n))次就会变成1, 因此可以考虑把一段相同的不为1的数缩成一个点,用平衡树来维护. 每次求p ...
随机推荐
- Codeforces 443 B Kolya and Tandem Repeat【暴力】
题意:给出一个字符串,给出k,可以向该字符串尾部添加k个字符串,求最长的连续重复两次的子串 没有想出来= =不知道最后添加的那k个字符应该怎么处理 后来看了题解,可以先把这k个字符填成'*',再暴力枚 ...
- [转]FFMPEG视音频编解码零基础学习方法
在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...
- HDU 3573 Buy Sticks (逻辑)
题意:a,b,c三种棍子长度分别为20,28,32,现需要这三种棍子数根,欲买长为75的棍子来剪成这三种(不够长的就废弃) ,问需要买多少根. 思路:将所有棍子尽可能和其他搭配起来,使得数量减到最少. ...
- php 调试工具及学习PHP垃圾回收机制了解引用计数器的概念
php代码工具:Xdebug 与分析工具 WinCacheGrind Xdebug之函数大全: string xdebug_call_class()返回当前被调用的函数或方法所属的类的类名 stri ...
- T-SQL备忘(4):分页
set statistics io on set statistics time on --SQL Server 2012分页方式 select * from Production.Product o ...
- mysql 数据库自增id 的总结
有一个表StuInfo,里面只有两列 StuID,StuName其中StuID是int型,主键,自增列.现在我要插入数据,让他自动的向上增长,insert into StuInfo(StuID,Stu ...
- s:iterator标签的使用
1.在说明s:iterator标签的使用前,先了解下struts2中的Value Stack. 这里参考了webwork中对Value Stack的描述,由于struts2是在webwork的基础上进 ...
- 【PHP入门到精通】:Ch05:字符串处理
Ch05: 字符串简介 5.1 字串说明 字符串是指由>=0个字符构成的一串字符,所以叫字符串.这里所说的字符主要包括以下几种类型:数字类型:如1, 2, 3, 4等.字母类型:如果a, b, ...
- strus2中获取表单数据 两种方式 属性驱动 和模型驱动
strus2中获取表单数据 两种方式 属性驱动 和模型驱动 属性驱动 /** * 当前请求的action在栈顶,ss是栈顶的元素,所以可以利用setValue方法赋值 * 如果一个属性在对象栈,在页面 ...
- C++模板实例掌握
前段时间重新学习C++,主要看C++编程思想和C++设计新思维.对模版的使用有了更进一层的了解,特总结如下: 下面列出了模版的常用情况: << '\n';} //参考:http://ww ...