【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 ...
随机推荐
- day22—一个AngularJS框架应用toDoList
转行学开发,代码100天——2018-04-07 今天用AngularJS照着课程写了一个案例,即toDoList,记事清单效果. 主要实现以下效果: 1.通过文本框添加内容,同时添加事件列表.主要用 ...
- 解读:nginx的一个神秘配置worker_cpu_affinity
今天在查看nginx的相关知识的时候发现了一个nginx之前不认识的配置:worker_cpu_affinity. nginx默认是没有开启利用多核cpu的配置的.需要通过增加worker_cpu_a ...
- tp框架视图层view——模板继承
在做网站的时候,每个网站都有头部和尾部,也就是菜单栏和页脚,网站的各个子网页的头部和尾部基本就是一样的,所以tp框架提供了一种模板继承的方法: 1.首先在View的Main文件夹下建立一个base.h ...
- Java8数据流
流/Stream是在JAVA8中引入的一个抽象,可以处理类似SQL语句声明数据. 例如,考虑下面的SQL语句. SELECT max(salary),employee_id,employee_name ...
- HTML5-新增type属性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Eclipse Kepler安装WST Server Adapter后创建Server无Tomcat解决方法
在Eclipse Kepler下安装完WST Server Adapter后,创建Server时发现没有Tomcat服务器的选项,这个问题解决起来很简单, 只需要安装一下JST Server Adap ...
- POJ-1611.TheSuspects.(并查集)
The Suspects Time Limit: 1000MS Memory Limit: 20000K Total Submissions: 55832 Accepted: 26501 De ...
- Java数组相关算法一
一.数组反转 1.方法一:创建新数组 int[] arr = {6,29,0,4,3}; int[] arr2 = new int[arr.length]; for (int i = 0; i < ...
- UVAlive 6756 Increasing Shortest Path
We all love short and direct problems, it is easier to write, read and understand the problem statem ...
- nginx的4层负载均衡配置
前言:所谓四层就是基于IP+端口的负载均衡:七层就是基于URL等应用层信息的负载均衡:同理,还有基于MAC地址的二层负载均衡和基于IP地址的三层负载均衡. 换句换说,二层负载均衡会通过一个虚拟MAC地 ...