【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 ...
随机推荐
- python web自动化测试框架搭建(功能&接口)——测试用例执行和结果收集
由于unittest框架中结果收集在不同文件中,所以此处重写结果收集方法,加入执行时间,失败信息,失败截图等 TestRunner.py # coding=utf-8 import sys impor ...
- 洛谷P1168 中位数——set/线段树
先上一波链接 https://www.luogu.com.cn/problem/P1168 这道题我们有两种写法 第一种呢是线段树,我们首先需要将原本的数据离散化,线段树维护的信息就是区间内有多少个数 ...
- mysql 主从复制 (2)
今天说一下MySQL的主从复制如何做到! 准备工作: 1.两个虚拟机:我这里用的是CentOS5.5,IP地址分别是192.168.1.101 和192.168.1.105: 101做主服务器,105 ...
- BZOJ 1937 (luogu 4412) (KM+LCA)
题面 传送门 分析 根据贪心的思想我们得到几条性质: 1.生成树上的边权减小,非树边的边权增加 2.每条边最多被修改一次 设改变量的绝对值为d 对于一条非树边\(j:(u,v)\),树上u->v ...
- 验证客户端的合法性、socketserver模块
一.为了防止客户端被人非法利用,需要在使用之前对客户端进行合法性验证.接下来就是客户端验证的几种方法 hmac 加密方法 import socket import os import hmac #能 ...
- 第一天学习如何使用markdown写日志,一起来看看成果吧!
目录 一级标题 二级标题 一级标题 二级标题 ==黄色== one two three one two three 性别 年龄 男 150 H~2~o hello markdown hello mar ...
- K The Right-angled Triangles
链接:https://ac.nowcoder.com/acm/contest/338/K来源:牛客网 题目描述 Consider the right-angled triangles with sid ...
- JS中的Number数据类型详解
Number数据类型 Number类型使用IEEE754格式来表示整数和浮点值,这也是0.2 + 0.3不等于0.5的原因, 最基本的数值类型字面量格式是十进制整数 var a = 10; 1. 浮点 ...
- GeneXus笔记本—GeneXusIDE如何切换成中文语言
嘛 有些人可能比较习惯英文IDE,但是有些人就比较难受 所以为了应对各个地区的差异 GeneXus很人性化的自带了一部分国家的语言包 只不过默认是英文 需要改动一下_(:з」∠)_ 右键你的IDE快捷 ...
- 大哥带我走渗透8--CSRF的应用
1.大哥给了一个CSRF实战视频,真的很简单,但是我今天晚上有点不在状态,很多简单的问题也没有想.所以做了一个多小时.这件事给我的启发就是,无论发生什么事,都不要影响自己的学习.先写点废话,真的真的, ...