2018.07.28 uoj#169. 【UR #11】元旦老人与数列(线段树)
传送门
线段树好题。
维护区间加,区间取最大值,维护区间最小值,历史区间最小值。
同样先考虑不用维护历史区间最小值的情况,这个可以参考这道题的解法,维护区间最小和次小值可以解决前两个操作,然后使用历史标记的常规维护方式合并标记更新就行了。
代码:
#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define N 500005
#define inf 2000000030
using namespace std;
struct Node{int l,r,sn,mn,add,his,his_add,his_mn,f;}T[N<<2];
int n,m,a[N];
inline int read(){
int ans=0,w=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans*w;
}
inline int min(int a,int b){return a<b?a:b;}
inline void pushup(int p){
T[p].his=min(T[lc].his,T[rc].his),T[lc].f=T[rc].f=0,T[p].mn=min(T[lc].mn,T[rc].mn);
T[p].sn=min(T[p].mn==T[lc].mn?T[lc].sn:T[lc].mn,T[p].mn==T[rc].mn?T[rc].sn:T[rc].mn);
if(T[lc].mn==T[p].mn)T[lc].f=1;
if(T[rc].mn==T[p].mn)T[rc].f=1;
}
inline void pushadd(int p,int v){
T[p].his_add=min(T[p].his_add,T[p].add+=v),T[p].sn+=v;
T[p].his=min(T[p].his,T[p].mn+=v),T[p].his_mn=min(T[p].his_mn,T[p].mn);
}
inline void pushset(int p,int v){if(T[p].mn>=v)return;T[p].mn=v;}
inline void pushdown(int p){
if(T[lc].f)T[lc].his=min(T[lc].his,T[p].his_mn),T[lc].his_mn=min(T[lc].his_mn,T[p].his_mn);
else T[lc].his=min(T[lc].his,T[lc].mn+T[p].his_add),T[lc].his_mn=min(T[lc].his_mn,T[lc].mn+T[p].his_add);
if(T[rc].f)T[rc].his=min(T[rc].his,T[p].his_mn),T[rc].his_mn=min(T[rc].his_mn,T[p].his_mn);
else T[rc].his=min(T[rc].his,T[rc].mn+T[p].his_add),T[rc].his_mn=min(T[rc].his_mn,T[rc].mn+T[p].his_add);
T[lc].mn+=T[p].add,T[rc].mn+=T[p].add,T[lc].sn+=T[p].add,T[rc].sn+=T[p].add;
T[lc].his_add=min(T[lc].his_add,T[lc].add+T[p].his_add);
T[rc].his_add=min(T[rc].his_add,T[rc].add+T[p].his_add);
T[lc].add+=T[p].add,T[rc].add+=T[p].add;
if(T[lc].mn<T[p].mn)T[lc].mn=T[p].mn;
if(T[rc].mn<T[p].mn)T[rc].mn=T[p].mn;
T[p].add=0,T[p].his_add=0,T[p].his_mn=inf;
}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r,T[p].add=T[p].his_add=0,T[p].his_mn=inf;
if(l==r){T[p].his=T[p].mn=a[l],T[p].sn=inf;return;}
build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int ql,int qr,int v){
if(ql>T[p].r||qr<T[p].l)return;
if(ql<=T[p].l&&T[p].r<=qr)return pushadd(p,v);
pushdown(p);
if(qr<=mid)update(lc,ql,qr,v);
else if(ql>mid)update(rc,ql,qr,v);
else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
pushup(p);
}
inline void modify(int p,int ql,int qr,int v){
if(ql>T[p].r||qr<T[p].l||T[p].mn>=v)return;
if(ql<=T[p].l&&T[p].r<=qr&&T[p].sn>v)return pushset(p,v);
pushdown(p);
if(qr<=mid)modify(lc,ql,qr,v);
else if(ql>mid)modify(rc,ql,qr,v);
else modify(lc,ql,mid,v),modify(rc,mid+1,qr,v);
pushup(p);
}
inline int query(int p,int ql,int qr,int k){
if(ql>T[p].r||qr<T[p].l)return inf;
if(ql<=T[p].l&&T[p].r<=qr)return k==3?T[p].mn:T[p].his;
pushdown(p);
if(qr<=mid)return query(lc,ql,qr,k);
if(ql>mid)return query(rc,ql,qr,k);
return min(query(lc,ql,mid,k),query(rc,mid+1,qr,k));
}
int main(){
n=read(),m=read();
for(register int i=1;i<=n;++i)a[i]=read();
build(1,1,n);
while(m--){
int op=read(),l=read(),r=read();
if(op==1){int v=read();update(1,l,r,v);}
else if(op==2){int v=read();modify(1,l,r,v);}
else printf("%d\n",query(1,l,r,op));
}
return 0;
}
update
在做了Picks loves segment tree VIII之后学习了新的写法,然后重新写了一遍。
代码:
#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define N 500005
#define inf 2e9
using namespace std;
inline int read(){
int ans=0,w=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans*w;
}
struct Min{int his,mn,sn;};
struct tag{int add,mnadd;};
struct Node{int l,r;Min mn;tag Amin,Bmid;}T[N<<2];
int n,m,a[N];
inline int min(int a,int b){return a<b?a:b;}
inline tag operator+(tag a,int v){return (tag){a.add+v,min(a.mnadd,a.add+v)};}
inline tag operator+(tag a,tag b){return (tag){a.add+b.add,min(a.mnadd,b.mnadd+a.add)};}
inline Min operator+(Min a,Min b){return (Min){min(a.his,b.his),min(a.mn,b.mn),a.mn==b.mn?min(a.sn,b.sn):(a.mn>b.mn?min(a.mn,b.sn):min(a.sn,b.mn))};}
inline void pushup(int p){T[p].mn=T[lc].mn+T[rc].mn;}
inline void pushadd(int p,int v){
T[p].mn.his=min(T[p].mn.his,T[p].mn.mn+=v);
if(T[p].mn.sn!=inf)T[p].mn.sn+=v;
T[p].Amin=T[p].Amin+v,T[p].Bmid=T[p].Bmid+v;
}
inline void pushAmin(int p,tag v){
T[p].mn.his=min(T[p].mn.his,T[p].mn.mn+v.mnadd);
T[p].mn.mn+=v.add;
T[p].Amin=T[p].Amin+v;
}
inline void pushBmid(int p,tag v){
if(T[p].mn.sn!=inf)T[p].mn.sn+=v.add;
T[p].Bmid=T[p].Bmid+v;
}
inline void pushdown(int p){
int tmpmn=min(T[lc].mn.mn,T[rc].mn.mn);
if(tmpmn==T[lc].mn.mn)pushAmin(lc,T[p].Amin);
else pushAmin(lc,T[p].Bmid);
pushBmid(lc,T[p].Bmid);
if(tmpmn==T[rc].mn.mn)pushAmin(rc,T[p].Amin);
else pushAmin(rc,T[p].Bmid);
pushBmid(rc,T[p].Bmid);
T[p].Amin=T[p].Bmid=(tag){0,0};
}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r,T[p].Amin=T[p].Bmid=(tag){0,0};
if(l==r){T[p].mn=(Min){a[l],a[l],inf};return;}
build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int ql,int qr,int v){
if(ql>T[p].r||qr<T[p].l)return;
if(ql<=T[p].l&&T[p].r<=qr)return pushadd(p,v);
pushdown(p);
if(qr<=mid)update(lc,ql,qr,v);
else if(ql>mid)update(rc,ql,qr,v);
else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
pushup(p);
}
inline void updmin(int p,int ql,int qr,int v){
if(ql>T[p].r||qr<T[p].l||T[p].mn.mn>=v)return;
if(ql<=T[p].l&&T[p].r<=qr&&T[p].mn.sn>v)return pushAmin(p,(tag){v-T[p].mn.mn,0});
pushdown(p);
if(qr<=mid)updmin(lc,ql,qr,v);
else if(ql>mid)updmin(rc,ql,qr,v);
else updmin(lc,ql,mid,v),updmin(rc,mid+1,qr,v);
pushup(p);
}
inline int query(int p,int ql,int qr){
if(ql>T[p].r||qr<T[p].l)return inf;
if(ql<=T[p].l&&T[p].r<=qr)return T[p].mn.mn;
pushdown(p);
if(qr<=mid)return query(lc,ql,qr);
if(ql>mid)return query(rc,ql,qr);
return min(query(lc,ql,mid),query(rc,mid+1,qr));
}
inline int querymn(int p,int ql,int qr){
if(ql>T[p].r||qr<T[p].l)return inf;
if(ql<=T[p].l&&T[p].r<=qr)return T[p].mn.his;
pushdown(p);
if(qr<=mid)return querymn(lc,ql,qr);
if(ql>mid)return querymn(rc,ql,qr);
return min(querymn(lc,ql,mid),querymn(rc,mid+1,qr));
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;++i)a[i]=read();
build(1,1,n);
while(m--){
int op=read(),l=read(),r=read();
if(op==1){int v=read();update(1,l,r,v);}
if(op==2){int v=read();updmin(1,l,r,v);}
if(op==3)printf("%d\n",query(1,l,r));
if(op==4)printf("%d\n",querymn(1,l,r));
}
return 0;
}
2018.07.28 uoj#169. 【UR #11】元旦老人与数列(线段树)的更多相关文章
- 2018.07.28 uoj#164. 【清华集训2015】V(线段树)
传送门 线段树好题. 要求支持的操作: 1.区间变成max(xi−a,0)" role="presentation" style="position: rela ...
- 2018.07.29~30 uoj#170. Picks loves segment tree VIII(线段树)
传送门 线段树好题. 维护区间取两种最值,区间加,求区间两种历史最值,区间最小值. 自己的写法调了一个晚上+一个上午+一个下午+一个晚上并没有调出来,90" role="prese ...
- uoj169:元旦老人与数列
题意:http://uoj.ac/problem/169 sol :线段树..........蜜汁TLE了一个点,不管了..... 代码抄snowMyDream的,orz........... 线段 ...
- ACM-ICPC 2018 南京赛区网络预赛 G Lpl and Energy-saving Lamps(线段树)
题目链接:https://nanti.jisuanke.com/t/30996 中文题目: 在喝茶的过程中,公主,除其他外,问为什么这样一个善良可爱的龙在城堡里被监禁Lpl?龙神秘地笑了笑,回答说这是 ...
- UOJ.52.[UR #4]元旦激光炮(交互 思路)
题目链接 \(Description\) 交互库中有三个排好序的,长度分别为\(n_a,n_b,n_c\)的数组\(a,b,c\).你需要求出所有元素中第\(k\)小的数.你可以调用至多\(100\) ...
- UOJ169. 【UR #11】元旦老人与数列
传送门 考虑用 \(segment~tree~beats\) 那一套理论,维护区间最小值 \(mn\) 和严格次小值 \(se\) 那么可以直接 \(mlog^2n\) 维护前三个操作 考虑维护历史最 ...
- 【UOJ#169】元旦老人与数列
论文题. 考虑到这题的维护和区间操作是反向的,也就是说无法像V那题快速的合并标记. 我们知道,一个区间的最小值和其他值是可以分开来维护的,因为如果一个区间被整体覆盖,那么最小值始终是最小值. 对于被覆 ...
- 入职第一个项目bug总结-2018/07/28
此项目是正式入职后的第一个项目,可能各种原因重重,导致测试提出了如此多的bug,关于那些因为需求不清楚而导致的就不说了,bug总结如下: 一.ElementUI table组件出现横向滚动条 原因:因 ...
- 【2018.07.28】(字符串/回文串)学习Manacher算法小记
主要是应用在回文串啦,原理也理解了老半天,如果没有图片的话,我也看不太懂它的原理 学习的灵感来源来自于:https://segmentfault.com/a/1190000008484167 /* 最 ...
随机推荐
- 怎样在本地windows安装和配置zookeeper
Zookeeper是什么?有什么用? Zookeeper是一个分布式协调服务. 作用:为用户的分布式应用程序提供协调服务. zookeeper在底层其实只提供了两个功能: 1.管理(存储,读取)用户 ...
- 使用java代码执行linux命令
前提: java代码是在windows下面写的,要打包放到linux下面运行,并且执行某个脚本. java代码: try { // 起作用的代码其实就下面这一行, 参数是linux中要执行的代码 Ru ...
- const 用法
static NSString * const testString = @"google"; //表示testString这个指针不能被修改,如若对testString赋值则会报 ...
- linux 中特殊符号用法详解
# 井号 (comments)#管理员 $普通用户 脚本中 #!/bin/bash #!/bin/sh井号也常出现在一行的开头,或者位于完整指令之后,这类情况表示符号后面的是注解文字,不会被执行 ...
- 分页导航jsp
<c:choose>标签与Java switch语句的功能一样,用于在众多选项中做出选择. switch语句中有case,而<c:choose>标签中对应有<c:when ...
- ubuntu 16.04 完整安装 phantomjs
摘自 stackoverflow sudo apt-get install nodejssudo apt-get install nodejs-legacysudo apt-get install n ...
- python 写hive循环脚本
要一个月的数据 一次跑一周的数据 ,建表用插入数据的方法: import os, sys reload(sys); sys.setdefaultencoding( "utf-8" ...
- linux sleep用法
应用程序:#include <syswait.h>usleep(n) //n微秒Sleep(n)//n毫秒sleep(n)//n秒驱动程序:#include <linux/delay ...
- webElement.text()获取到内容为空
使用webElement.text()方法获取字符串时,有时候会获取失败--获取到的内容为空 使用 webElement.getAttribute("attributeName") ...
- sqlserver批量导出存储过程、函数、视图
select text from syscomments s1 join sysobjects s2 on s1.id=s2.id where xtype = 'V' xtype V 视图 P ...