HDU 5828 Rikka with Sequence
好久没写线段树了,这题作为一个回味..
第一种操作的话,就是一个延迟标记。
第二种操作可以暴力更新下去,但是有一个优化,如果某区间内所有值都是一样的,或者最大值和最小值相差1,那么到此结束,不要继续往下面更新了。
这样一来的话,pushDown的时候要注意一下,如果该区间内所有值都一样,或者最大值和最小值相差1,那么延迟标记不要往下扔了,直接把该区间的信息传下去。如果该区间内所有值不一样,将延迟标记扔下去。
总体难度不算大,仔细一些就能AC。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-;
void File()
{
freopen("D:\\in.txt","r",stdin);
freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x) {
char c = getchar(); x = ;while(!isdigit(c)) c = getchar();
while(isdigit(c)) { x = x * + c - ''; c = getchar(); }
} const int maxn=+;
struct Seg { LL sum,f,MAX,MIN; }s[*maxn];
int T,n,m; void pushUp(int rt)
{
s[rt].sum=s[*rt].sum+s[*rt+].sum;
s[rt].MAX=max(s[*rt].MAX,s[*rt+].MAX);
s[rt].MIN=min(s[*rt].MIN,s[*rt+].MIN);
} void pushDown(int l,int r,int rt)
{
if(s[rt].MIN==s[rt].MAX)
{
s[*rt].MIN=s[*rt+].MIN=s[rt].MIN;
s[*rt].MAX=s[*rt+].MAX=s[rt].MAX; int fz=(l+r)/-l+;
s[*rt].sum=(LL)fz*s[rt].MIN;
s[*rt+].sum=s[rt].sum-s[*rt].sum;
s[rt].f=s[*rt].f=s[*rt+].f=;
return;
} if(s[rt].MIN==s[rt].MAX-)
{
int Tmin=min(s[*rt].MIN,s[*rt+].MIN),Tmax=max(s[*rt].MAX,s[*rt+].MAX); int len,x1,x2;
if(s[*rt].MIN==s[*rt].MAX)
{
if(s[*rt].MIN==Tmin) s[*rt].MIN=s[*rt].MAX=s[rt].MIN;
else s[*rt].MIN=s[*rt].MAX=s[rt].MAX;
s[*rt].sum=(LL)((l+r)/-l+)*s[*rt].MIN;
}
else
{
len=(l+r)/-l+;
x1=(s[*rt].sum-s[*rt].MAX*(LL)len)/(s[*rt].MIN-s[*rt].MAX); x2=len-x1;
s[*rt].MAX=s[rt].MAX; s[*rt].MIN=s[rt].MIN;
s[*rt].sum=(LL)x1*s[*rt].MIN+(LL)x2*s[*rt].MAX;
} if(s[*rt+].MIN==s[*rt+].MAX)
{
if(s[*rt+].MIN==Tmin) s[*rt+].MIN=s[*rt+].MAX=s[rt].MIN;
else s[*rt+].MIN=s[*rt+].MAX=s[rt].MAX;
s[*rt+].sum=(r-(l+r)/)*s[*rt+].MIN;
}
else
{
len=r-(l+r)/;
x1=(s[*rt+].sum-s[*rt+].MAX*(LL)len)/(s[*rt+].MIN-s[*rt+].MAX); x2=len-x1;
s[*rt+].MAX=s[rt].MAX; s[*rt+].MIN=s[rt].MIN;
s[*rt+].sum=(LL)x1*s[*rt+].MIN+(LL)x2*s[*rt+].MAX;
}
s[rt].f=s[*rt].f=s[*rt+].f=;
return;
} if(s[rt].f==) return; s[*rt].f=s[*rt].f+s[rt].f;
s[*rt+].f=s[*rt+].f+s[rt].f; s[*rt].MAX=s[*rt].MAX+s[rt].f;
s[*rt+].MAX=s[*rt+].MAX+s[rt].f; s[*rt].MIN=s[*rt].MIN+s[rt].f;
s[*rt+].MIN=s[*rt+].MIN+s[rt].f; int m=(l+r)/;
s[*rt].sum=s[*rt].sum+(LL)(m-l+)*s[rt].f;
s[*rt+].sum=s[*rt+].sum+(LL)(r-m)*s[rt].f; s[rt].f=;
} void build(int l,int r,int rt)
{
s[rt].f=; s[rt].MAX=; s[rt].MIN=; s[rt].sum=;
if(l==r)
{
read(s[rt].sum);
s[rt].f=; s[rt].MAX=s[rt].sum; s[rt].MIN=s[rt].sum;
return;
}
int m=(l+r)/;
build(l,m,*rt);
build(m+,r,*rt+);
pushUp(rt);
} void add(int L,int R,int x,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
s[rt].f=s[rt].f+x; s[rt].MAX=s[rt].MAX+x;
s[rt].MIN=s[rt].MIN+x; s[rt].sum=s[rt].sum+(r-l+)*(LL)x;
return;
}
pushDown(l,r,rt);
int m=(l+r)/;
if(L<=m) add(L,R,x,l,m,*rt);
if(R>m) add(L,R,x,m+,r,*rt+);
pushUp(rt);
} LL quary(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R) return s[rt].sum;
pushDown(l,r,rt);
int m=(l+r)/; LL x1=,x2=;
if(L<=m) x1=quary(L,R,l,m,*rt);
if(R>m) x2=quary(L,R,m+,r,*rt+);
pushUp(rt);
return x1+x2;
} void force(int l,int r,int rt)
{
if(l==r)
{
s[rt].sum=(LL)sqrt(1.0*s[rt].sum);
s[rt].MIN=s[rt].MAX=s[rt].sum;
return;
}
if(s[rt].MIN==s[rt].MAX)
{
s[rt].MAX=s[rt].MIN=(LL)sqrt(1.0*s[rt].MIN);
s[rt].sum=(LL)(r-l+)*s[rt].MIN;
return;
} if(s[rt].MIN==s[rt].MAX-)
{
int len=r-l+;
int x1=(s[rt].sum-s[rt].MAX*(LL)len)/(s[rt].MIN-s[rt].MAX), x2=len-x1;
s[rt].MAX=(LL)sqrt(1.0*s[rt].MAX);
s[rt].MIN=(LL)sqrt(1.0*s[rt].MIN);
s[rt].sum=(LL)x1*s[rt].MIN+(LL)x2*s[rt].MAX; return;
} pushDown(l,r,rt);
int m=(l+r)/;
if(s[*rt].MAX!=) force(l,m,*rt);
if(s[*rt+].MAX!=) force(m+,r,*rt+);
pushUp(rt);
} void update(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R) { if(s[rt].MAX==) return; force(l,r,rt); return; }
pushDown(l,r,rt);
int m=(l+r)/;
if(L<=m&&s[*rt].MAX!=) update(L,R,l,m,*rt);
if(R>m&&s[*rt+].MAX!=) update(L,R,m+,r,*rt+);
pushUp(rt);
} int main()
{
scanf("%d",&T); while(T--)
{
read(n); read(m); build(,n,);
for(int i=;i<=m;i++)
{
int op,L,R,x;
read(op); read(L); read(R);
if(op==) { read(x); add(L,R,x,,n,); }
else if(op==) update(L,R,,n,);
else if(op==) printf("%lld\n",quary(L,R,,n,));
}
}
return ;
}
HDU 5828 Rikka with Sequence的更多相关文章
- 判断相同区间(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 题目连接: 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 5828 Rikka with Sequence (线段树+剪枝优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是 ...
- HDU 5828 Rikka with Sequence(线段树)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5828 [题目大意] 给出一个数列,要求支持区间加法,区间开方和区间和查询操作. [题解] 考虑开方 ...
- HDU 5828 Rikka with Sequence(线段树区间加开根求和)
Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...
- hdu 5204 Rikka with sequence 智商不够系列
Rikka with sequence Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.p ...
- HDU - 6087 Rikka with Sequence (可持久化treap+倍增+重构)
题目链接 感谢Dream_Lolita的题解,经过无数次失败的尝试之后终于AC了... 线段树是维护区间信息的强大工具,但它的形态是固定的,只支持修改和删除操作,不支持插入.反转.复制.分裂合并等操作 ...
随机推荐
- code style
http://www.jianshu.com/p/0a984f999592# https://github.com/drakeet/LayoutFormatter https://github.com ...
- we are happy 把空格换成 %20 剑指offer P44
public class StringReplace { public static void replaceSpace(String[] str, int length) { if(str == n ...
- JavaScript——Cookie
JavaScript中的Cookie基础 页面用来保存信息的,比如登录.记住用户名. [cookie的特性] (1)同一个网站中所有页面共享一套cookie: (2)数量.大小有限: (3)有保质期, ...
- Hibernate使用原生SQL(转载)
本文转载,出处如下:http://bhdweb.iteye.com/blog/801084 HQL尽管容易使用,但是在一些复杂的数据操作上功能有限.特别是在实现复杂的报表统计与计算,以及多表连接查询上 ...
- ios 实现在tableViewCell上面添加长按手势 删除该条cell以及列表后台数据等
自己的代码 需要 把属性更改成自己要使用的 //创建长按手势 在cellForRowAtIndexPath代理方法中 UILongPressGestureRecognizer *longPres ...
- DPDK l2fwd 浅注
l2fwd是DPDK中的非常经典的例子.二层转发模型. 就是在相邻的网卡接口间互相传递报文. 网口0和网口1之间报文互传. 网口2和网口3之间报文互传. ............ 运行参数 . 在目录 ...
- iOS开发讯飞语音的集成
1.进入官网注册账号,登陆,注册,应用. 2,下载sdk 导入系统库. 3,关闭bitcode 4,初始化讯飞语音. NSString * initString = [[NSString alloc ...
- 整体认识flume:Flume介绍、分布式安装、常见问题及解决方案
问题导读 1.什么是flume? 2.flume包含哪些组件? 3.Flume在读取utf-8格式的文件时会出现解析不了时间戳,该如何解决? Flume是一个分布式.可靠.和高可用的海量日志采集.聚合 ...
- aps.net 页面事件执行顺序
- Computation expressions and wrapper types
原文地址:http://fsharpforfunandprofit.com/posts/computation-expressions-wrapper-types/ 在上一篇中,我们介绍了“maybe ...