传送门

线段树好题。

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

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

代码:

#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. FDConnection

    FDConnection 利用FDConnection获取信息,不用放query控件也可以.   FDConnection1.GetTableNames('', '', '', List);   FD ...

  2. 原生js实现三级复选框

    工作中要做一个三级的复选框,用js实现了一下,从项目中把相关代码抽取出来了,有相关需求的可以参考一下.亲测可用. <!DOCTYPE html> <html> <head ...

  3. How to Pronounce Ending T Clusters + Homophones — Baking!

    How to Pronounce Ending T Clusters + Homophones — Baking! Share Tweet Share Tagged With: ARE Reducti ...

  4. Social media users of the world unite!

    Social media users of the world unite!全世界社交媒体用户联合起来!If Plato were alive today, he might well regard ...

  5. 迷你MVVM框架 avalonjs 1.3.7发布

    又到每个月的15号了,现在avalon已经固定在每个月的15号发布新版本.这次发布又带来许多新特性,让大家写码更加轻松,借助于"操作数据即操作DOM"的核心理念与双向绑定机制,现在 ...

  6. 安装 neo4j 在 .../bin 目录下使用 ./neo4j 没反应 和 从csv 导入数据到neo4j

    可以使用 /bin/sh ./neo4j start 如果提示:./neo4j: 28: set: Illegal option -o pipefail 那么 ubuntu”set Illegal o ...

  7. js中常见的创建对象的方法

    前两天好好的把高程对象那一块又读了下,顺便写点笔记.补一句:代码都测试过了,应该没有问题的.可以直接拿到控制台跑! 1.工厂模式 function person(name, age, job) { v ...

  8. DNS使用的是TCP协议还是UDP协议

    原文:http://benbenxiongyuan.iteye.com/blog/1088085 DNS同时占用UDP和TCP端口53是公认的,这种单个应用协议同时使用两种传输协议的情况在TCP/IP ...

  9. Python int() 函数

    Python int() 函数  Python 内置函数 描述 int() 函数用于将一个字符串或数字转换为整型. 语法 以下是 int() 方法的语法: class int(x, base=10) ...

  10. Python bin() 函数

    Python bin() 函数  Python 内置函数 描述 bin() 返回一个整数 int 或者长整数 long int 的二进制表示. 语法 以下是 bin() 方法的语法: bin(x) 参 ...