传送门

线段树好题。

维护区间加,区间取最大值,维护区间最小值,历史区间最小值。

同样先考虑不用维护历史区间最小值的情况,这个可以参考这道题的解法,维护区间最小和次小值可以解决前两个操作,然后使用历史标记的常规维护方式合并标记更新就行了。

代码:

#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】元旦老人与数列(线段树)的更多相关文章

  1. 2018.07.28 uoj#164. 【清华集训2015】V(线段树)

    传送门 线段树好题. 要求支持的操作: 1.区间变成max(xi−a,0)" role="presentation" style="position: rela ...

  2. 2018.07.29~30 uoj#170. Picks loves segment tree VIII(线段树)

    传送门 线段树好题. 维护区间取两种最值,区间加,求区间两种历史最值,区间最小值. 自己的写法调了一个晚上+一个上午+一个下午+一个晚上并没有调出来,90" role="prese ...

  3. uoj169:元旦老人与数列

    题意:http://uoj.ac/problem/169 sol  :线段树..........蜜汁TLE了一个点,不管了..... 代码抄snowMyDream的,orz........... 线段 ...

  4. ACM-ICPC 2018 南京赛区网络预赛 G Lpl and Energy-saving Lamps(线段树)

    题目链接:https://nanti.jisuanke.com/t/30996 中文题目: 在喝茶的过程中,公主,除其他外,问为什么这样一个善良可爱的龙在城堡里被监禁Lpl?龙神秘地笑了笑,回答说这是 ...

  5. UOJ.52.[UR #4]元旦激光炮(交互 思路)

    题目链接 \(Description\) 交互库中有三个排好序的,长度分别为\(n_a,n_b,n_c\)的数组\(a,b,c\).你需要求出所有元素中第\(k\)小的数.你可以调用至多\(100\) ...

  6. UOJ169. 【UR #11】元旦老人与数列

    传送门 考虑用 \(segment~tree~beats\) 那一套理论,维护区间最小值 \(mn\) 和严格次小值 \(se\) 那么可以直接 \(mlog^2n\) 维护前三个操作 考虑维护历史最 ...

  7. 【UOJ#169】元旦老人与数列

    论文题. 考虑到这题的维护和区间操作是反向的,也就是说无法像V那题快速的合并标记. 我们知道,一个区间的最小值和其他值是可以分开来维护的,因为如果一个区间被整体覆盖,那么最小值始终是最小值. 对于被覆 ...

  8. 入职第一个项目bug总结-2018/07/28

    此项目是正式入职后的第一个项目,可能各种原因重重,导致测试提出了如此多的bug,关于那些因为需求不清楚而导致的就不说了,bug总结如下: 一.ElementUI table组件出现横向滚动条 原因:因 ...

  9. 【2018.07.28】(字符串/回文串)学习Manacher算法小记

    主要是应用在回文串啦,原理也理解了老半天,如果没有图片的话,我也看不太懂它的原理 学习的灵感来源来自于:https://segmentfault.com/a/1190000008484167 /* 最 ...

随机推荐

  1. jquery checkbox

    $(document).ready(function() { var $cr = $("#cr"); var cr = $cr[0]; $cr.click(function() { ...

  2. 用FireDAC获取 SQL SERVER错误文本信息

    SQL SERVER获取错误文本信息,BDE.adoquery一直取不到,FDQuery可以了 Some DBMS, like SQL Server, return messages as an ad ...

  3. Simple2D-22(重构)纹理池

    以前 Simple2D 使用 TextureManager,现在将它改为 TexturePool (纹理池).主要是负责加载和管理纹理,这次为 TexturePool 添加纹理集的功能,纹理集就是将大 ...

  4. WDA-参考路径

    1. SAP Netweave安装 https://wenku.baidu.com/view/b3ac371a227916888486d77c.html?sxts=1545717961793   2. ...

  5. java流输入输出

    java读取txt文件内容.可以作如下理解:  首先获得一个文件句柄.File file = new File(); file即为文件句柄.两人之间连通电话网络了.接下来可以开始打电话了.  通过这条 ...

  6. How to Pronounce BEAUTIFUL

    How to Pronounce BEAUTIFUL Share Tweet Share Tagged With: 3-Syllable Can you say this word beautiful ...

  7. Haskell语言学习笔记(22)MaybeT

    Monad Transformers Monad 转换器用于将两个不同的Monad合成为一个Monad.Monad 转换器本身也是一个 Monad. MaybeT MaybeT 这个 Monad 转换 ...

  8. 树莓派Zero W添加音频输出

    编译:陈拓 chentuo@ms.xab.ac.cn 2018.06.07/2018.07.14 原文:Adding Basic Audio Ouput to Raspberry Pi Zero ht ...

  9. Hibernate 中 联合主键映射 组合关系映射 大对象映射(或者说文本大对象,二进制数据大对象)

    Clob:文本大对象,最长4G Blob:二进制数据大对象,最长4G util: public class HibUtil { private static SessionFactory sessio ...

  10. SOA (面向服务的架构)

    面向服务的体系结构,是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来.接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台.操作系统和编程语 ...