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 /* 最 ...
随机推荐
- Gradle 语法
参考文章: Gradle学习系列之二——创建Task的多种方法(http://www.cnblogs.com/CloudTeng/p/3417970.html) Gradle基本知识点与常用配置(ht ...
- (转载)session token机制
http://blog.chinaunix.net/uid-26642709-id-3061264.html 使用session token时,必须用struts2表标签库,不能用html 通过ses ...
- JAVA中request.getParameterMap()用法笔记
一. 根据Java规范:request.getParameterMap()返回的是一个Map类型的值,该返回值记录着前端(如jsp页面)所提交请求中的请求参数和请求参数值的映射关系.这个返回值有个特别 ...
- How to Pronounce the I in ING
How to Pronounce the I in ING Share Tweet Share Tagged With: ING Verbs The I in ING is the IH as in ...
- To zero
Let bygone be bygone. Now everything changed. In fact, everything occurs to me cause I am a loser i ...
- iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 记录日志
沪江CCtalk视频地址:https://www.cctalk.com/v/15114923883523 log 日志中间件 最困难的事情就是认识自己. 在一个真实的项目中,开发只是整个投入的一小部分 ...
- mysql 用户及赋予权限
查询用户: use mysql; select host,user from mysql.user; 创建用户: create user 'mhc'@'%' identified by 'mhc.12 ...
- What is API Level?
[What is API Level?] 参考:http://android.xsoftlab.net/guide/topics/manifest/uses-sdk-element.html#ApiL ...
- SearchEngine Note
[SearchEngine Note] 1.查全率. 2.查准率. 3.查全率与查准率的关系. 4.四大系统. 5.权威性网页反向链接多.网页的平均出席为25.7,即平均每一个网页含有25.7个指向其 ...
- WebDriverException: Message: f.QueryInterface is not a function
WebDriverException: Message: f.QueryInterface is not a function 使用webdriver打开c.highpin.cn,结果报错,见下图: ...