【HDU5306】【DTOJ2481】Gorgeous Sequence【线段树】

题目大意:给你一个序列a,你有三个操作,0: x y t将a[x,y]和t取min;1:x y求a[x,y]的最大值;2:x y求a[x,y]的sum
题解:首先很明显就是线段树裸题,那么考虑如何维护
区间最大值和区间sum很好维护,0操作不好做,那么考虑怎么快速解决0操作
很容易想到维护区间最大值和区间是否全部相同,这是一个做法,但是时间复杂度上却不正确,但也给了我们一个思路,可以通过维护最大值之类的数来加快操作
一个不行就两个,于是考虑维护次大值,那么每次0操作就有三种情况,一:比区间最大值还大,那么直接返回;二:大于区间次大值小于区间最大值,那么可以直接修改区间;三:小于区间次大值,那么继续递归下去;
这么做是可行的,在更新区间时因为要维护sum值,于是多维护一个区间max有多少个即可
证明略,时间复杂度o(nlog^2n)——来源:吉老师
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#define ll long long
using namespace std;
int T,n,m;
ll a[];
class Segtree
{
public:
ll sum[*],mx[*],smx[*],cnt[*],fl[*]; void pushup(int pos)
{
sum[pos]=sum[pos<<]+sum[pos<<|];
if(mx[pos<<]>mx[pos<<|])
{
mx[pos]=mx[pos<<];
cnt[pos]=cnt[pos<<];
if(mx[pos<<|]>smx[pos<<])smx[pos]=mx[pos<<|];
else smx[pos]=smx[pos<<];
}
if(mx[pos<<]<mx[pos<<|])
{
mx[pos]=mx[pos<<|];
cnt[pos]=cnt[pos<<|];
if(mx[pos<<]>smx[pos<<|])smx[pos]=mx[pos<<];
else smx[pos]=smx[pos<<|];
}
if(mx[pos<<]==mx[pos<<|])
{
mx[pos]=mx[pos<<];
cnt[pos]=cnt[pos<<]+cnt[pos<<|];
if(smx[pos<<]>smx[pos<<|])smx[pos]=smx[pos<<];
else smx[pos]=smx[pos<<|];
}
}
void pushdown(int pos)
{
if(fl[pos]>=)
{
if(mx[pos<<]>fl[pos])
{
sum[pos<<]-=(mx[pos<<]-fl[pos])*cnt[pos<<];
fl[pos<<]=mx[pos<<]=fl[pos];
}
if(mx[pos<<|]>fl[pos])
{
sum[pos<<|]-=(mx[pos<<|]-fl[pos])*cnt[pos<<|];
fl[pos<<|]=mx[pos<<|]=fl[pos];
}
fl[pos]=-;
}
}
void build(int l,int r,int pos)
{
if(l==r)
{
sum[pos]=mx[pos]=a[l];
cnt[pos]=;
fl[pos]=smx[pos]=-;
return;
}
int mid=l+r>>;
build(l,mid,pos<<);
build(mid+,r,pos<<|);
pushup(pos);
fl[pos]=-;
}
void change(int l,int r,int al,int ar,ll v,int pos)
{
int mid=l+r>>;
if(l==al && r==ar)
{
if(v>=mx[pos])return;
if(smx[pos]<v && v<mx[pos])
{
sum[pos]-=(mx[pos]-v)*cnt[pos];
fl[pos]=mx[pos]=v;
return;
}
change(l,mid,al,mid,v,pos<<);
change(mid+,r,mid+,ar,v,pos<<|);
pushup(pos);
return;
}
pushdown(pos);
if(ar<=mid)change(l,mid,al,ar,v,pos<<);
if(al>mid)change(mid+,r,al,ar,v,pos<<|);
if(al<=mid && ar>mid){change(l,mid,al,mid,v,pos<<);change(mid+,r,mid+,ar,v,pos<<|);}
pushup(pos);
}
ll askmax(int l,int r,int al,int ar,int pos)
{
if(l==al && r==ar)return mx[pos];
int mid=l+r>>;
pushdown(pos);
if(ar<=mid)return askmax(l,mid,al,ar,pos<<);
if(al>mid)return askmax(mid+,r,al,ar,pos<<|);
if(al<=mid && ar>mid)
{
ll t1=askmax(l,mid,al,mid,pos<<),t2=askmax(mid+,r,mid+,ar,pos<<|);
return t1>t2?t1:t2;
}
}
ll asksum(int l,int r,int al,int ar,int pos)
{
if(l==al && r==ar)return sum[pos];
int mid=l+r>>;
pushdown(pos);
if(ar<=mid)return asksum(l,mid,al,ar,pos<<);
if(al>mid)return asksum(mid+,r,al,ar,pos<<|);
if(al<=mid && ar>mid)return asksum(l,mid,al,mid,pos<<)+asksum(mid+,r,mid+,ar,pos<<|);
}
}segtree;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%lld",&a[i]);
segtree.build(,n,);
int mod,x,y;ll t;
while(m--)
{
scanf("%d",&mod);
if(mod==)
{
scanf("%d%d%lld",&x,&y,&t);
segtree.change(,n,x,y,t,);
}
if(mod==)
{
scanf("%d%d",&x,&y);
printf("%lld\n",segtree.askmax(,n,x,y,));
}
if(mod==)
{
scanf("%d%d",&x,&y);
printf("%lld\n",segtree.asksum(,n,x,y,));
}
}
}
return ;
}
心得:有时候多维护一个次大值能解决很多问题,更多时候在不知道如何证明时间复杂度的情况下往往维护次大值是正确的
【HDU5306】【DTOJ2481】Gorgeous Sequence【线段树】的更多相关文章
- 【hdu5306】Gorgeous Sequence 线段树区间最值操作
题目描述 给你一个序列,支持三种操作: $0\ x\ y\ t$ :将 $[x,y]$ 内大于 $t$ 的数变为 $t$ :$1\ x\ y$ :求 $[x,y]$ 内所有数的最大值:$2\ x\ y ...
- HDU 5306 Gorgeous Sequence[线段树区间最值操作]
Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- HDOJ 5306 Gorgeous Sequence 线段树
http://www.shuizilong.com/house/archives/hdu-5306-gorgeous-sequence/ Gorgeous Sequence Time Limit: 6 ...
- HDU - 5306 Gorgeous Sequence 线段树 + 均摊分析
Code: #include<algorithm> #include<cstdio> #include<cstring> #define ll long long ...
- 2016暑假多校联合---Rikka with Sequence (线段树)
2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...
- Wow! Such Sequence!(线段树4893)
Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
- Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间取摸
D. The Child and Sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...
- hdu4893Wow! Such Sequence! (线段树)
Problem Description Recently, Doge got a funny birthday present from his new friend, Protein Tiger f ...
- HDU 6047 Maximum Sequence(线段树)
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=6047 题目: Maximum Sequence Time Limit: 4000/2000 MS (J ...
- Codeforces 438D The Child and Sequence - 线段树
At the children's day, the child came to Picks's house, and messed his house up. Picks was angry at ...
随机推荐
- 建站手册-template
ylbtech-建站手册: 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 作者:ylbtech出处:http://ylbtech.cn ...
- mysql_DML_select_升序降序去重
select *from wsb limit 5;显示前5行 select *from students LIMIT (m,n) (其中m是指记录开始的index,从0开始,表示第一条记录n是指 ...
- day33—前端开发的模块化和组件化
转行学开发,代码100天——2018-04-18 今天是记录前端开发中模块化.组件化的知识.关于何为模块化,何为组件化以及为何要如此,目前还是处于一个只可意会不可言传的理解应用阶段. 当然,这样的存在 ...
- HttpSessionBindingListener和HttpSessionAttributeListener区别
HttpSessionBindingListener和HttpSessionAttributeListener是两个经常让初学者弄混的监听器,其实它们有很大的区别.这2个监听器在文章中简称为Bindi ...
- Linux_Bash常用脚本
目录 目录 从用户列表中过滤用户名并创建用户 awktrcut 指令的文本处理 tr指令 cut指令 awk指令 备份文件 测试LFTPServer权限设定 开启Httpd 安装Httpd 批量创建用 ...
- Git是目前世界上最先进的分布式版本控制系统(没有之一)。
http://zhidao.baidu.com/link?url=NSYPiSvtGTMoqMA9vt68FRRF8WbfYVmwWeMh47_2lkp0K3jFMl--1Co1tg1R4VshTQV ...
- vue项目运行时出现的问题(less、vue poackages version)
今天运行项目,项目一直好好的却突然运行时报错,如下: 是引入文件报错问题,回头查看了一下文件在main.js的引入: import '@/assets/styles/custom.less'; 文件引 ...
- Java thread(2)
这一块主要是从Thread类源码的角度来分析两种线程的实现方式,这里分析的也仅仅是最基本的部分. 就从线程的启动函数 start方法开始分析 只是分析最主要的部分 在start()方法中,除了grou ...
- servlet--三大域
requset \ session servletContext application
- 如何在Python中使用Linux epoll
如何在Python中使用Linux epoll 内容 介绍 阻塞套接字编程示例 异步套接字和Linux epoll的好处 epoll的异步套接字编程示例 性能考量 源代码 介绍 从2.6版开始,Pyt ...