【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 ...
随机推荐
- TODO 思维模型 尺子 游标卡尺
100个人 两个思维切入点 1>做对的题怎么分配 m(x)表示答对x道题的最多人数f(x)表示答对x道题的人数 m(0)=5m(1)=20=>f(0)=0m(2)=m(1)+1=21=&g ...
- zookeeper centos分布式安装使用
1. 请先安装jdk和下载zookeeper.ssh免密登录请自行配置.大家可以到官网下载或我的网盘. 网盘地址: 共3台机器c0,c1,c2 192.168.132.148 c0192.168.13 ...
- Entity Framework Code First属性映射约定 转载https://www.cnblogs.com/libingql/p/3352058.html
Entity Framework Code First属性映射约定 Entity Framework Code First与数据表之间的映射方式有两种实现:Data Annotation和Flue ...
- 【OpenGL】---认识CubeTexture
一.OpenGL Cube Texture 立方体纹理 立方体纹理是一种特殊的纹理技术,他用6幅二维贴图构成一个以原点为中心的纹理立方体.对于每个片段,纹理坐标(s,t,r)被当做三维向量看待,每个纹 ...
- DbWrench002--建模以及数据正向工程和反向工程的具体操作
DbWrench--建模以及数据正向工程和反向工程 参考博客:https://my.oschina.net/u/3459265/blog/1611999 一.数据正向工程 在建模工作中画好的表与表之间 ...
- C#将字符串Split()成数组
string str="aaajbbbjccc";string[] sArray=str.Split('j');foreach(string i in sArray) Respon ...
- python——列表操作函数和方法
1.添加新元素 1.1 append()函数 描述:append() 方法用于在列表末尾添加新的对象. 语法:list.append(obj) 参数:obj -- 添加到列表末尾的对象. 返回值:该方 ...
- JVM(3) 之 内存分配与回收策略
开发十年,就只剩下这套架构体系了! >>> 之前讲过虚拟机中的堆,他是整个内存模型中占用最大的一部分,而且不是连续的.当有需要分配内存的时候,一般有两个方法分配,指针碰撞和空闲列 ...
- GeneXus笔记本—常用函数(上)
国庆放假没事怎么办?写点笔记充会儿电! ≖‿≖✧ 哈哈哈 !!最近在参与公司的其中一个项目中,发现了一些函数自己没见过 也没使用过,但是这些函数都是GeneXus中自带的一些 这此记录的目的就是为 ...
- 二 shell 基础
一 文件的 权限基础 文件有三类权限 user,group,other, 权限分为 r w x 代表数字分别为 4 2 1 修改权限命令 chmod 权限还有特殊权限,在执行的时候代表某一身 ...