UOJ164 V 线段树lazytag维护历史最值

原创 2017年01月15日 20:10:16

题意:维护一列数,支持:
1.区间加A
2.区间减A,减法结束后每个位置与0取max
3.区间覆盖成A
4.询问单点当前值
5.询问单点历史最值

线段树lazytag维护历史最值,要记录四个数组,注意转移以及初始条件。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn=10000010;
const LL INF=1e18;
int n,m;
struct Tree{
    LL add,addmax,r,rmax;
}tree[maxn<<2],tmp;
int qx;
int ql,qr;
int type;
LL s[maxn];
void build(int o,int l,int r){
    if(l==r){
        tree[o]=(Tree){0,0,-INF,-INF};
        return;
    }
    int lc=o<<1,rc=o<<1|1,mid=(l+r)>>1;
    build(lc,l,mid);
    build(rc,mid+1,r);
}
Tree update(Tree u,Tree v){
    return (Tree){
        max(u.add+v.add,-INF),max(u.addmax,u.add+v.addmax),max(u.r+v.add,v.r),max(max(u.rmax,v.rmax),u.r+v.addmax)
    };
}
void pushdown(int o){
    tree[o<<1]=update(tree[o<<1],tree[o]);
    tree[o<<1|1]=update(tree[o<<1|1],tree[o]);
    tree[o]=(Tree){0,-INF,0,-INF};
}
void change(int o,int l,int r){
    if(ql<=l && qr>=r){
        tree[o]=update(tree[o],tmp);
        return;
    }
    pushdown(o);
    int lc=o<<1,rc=o<<1|1,mid=(l+r)>>1;
    if(ql<=mid) change(lc,l,mid);
    if(qr>mid) change(rc,mid+1,r);
}
void query(int o,int l,int r){
    if(l==r){
        if(type==4) printf("%lld\n",max(tree[o].add+s[qx],tree[o].r));
        if(type==5) printf("%lld\n",max(tree[o].addmax+s[qx],tree[o].rmax));
        return;
    }
    pushdown(o);
    int lc=o<<1,rc=o<<1|1,mid=(l+r)>>1;
    if(qx<=mid) query(lc,l,mid);
    else query(rc,mid+1,r);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&s[i]);
    build(1,1,n);
    while(m--){
        scanf("%d",&type);
        int x;
        if(type<=3){
            scanf("%d%d",&ql,&qr);
            scanf("%d",&x);
            if(type==1)tmp=(Tree){x,x,-INF,-INF};
            if(type==2)tmp=(Tree){-x,-x,0,0};
            if(type==3)tmp=(Tree){-INF,-INF,x,x};
            change(1,1,n);
        }else{
            scanf("%d",&qx);
            query(1,1,n);
        }
    }
    return 0;
}

^_^

版权声明:本文为博主原创文章,未经博主允许不得转载。

[UOJ164] V 记录历史最值线段树

令标记为表示对这个区间加p后和c取max 再多来两个标记记录两次修改间这个节点所能得到的最大标记是多少 诶写线段树之前真应该把标记加法和节点加法先在草稿纸上写好以后再开始敲 不然写起来很难受 #inc...
  • di4CoveRy
  • di4CoveRy
  • 2017年01月15日 23:07
  • 416

UOJ 164 线段树历史最值

164. 【清华集训2015】V描述 提交 自定义测试 Picks博士观察完金星凌日后,设计了一个复杂的电阻器。为了简化题目,题目中的常数与现实世界有所不同。这个电阻器内有编号为 1∼n1∼n 的 n...
  • miaomiao_ymxl
  • miaomiao_ymxl
  • 2017年01月16日 21:38
  • 405

uoj164. 【清华集训2015】V

Picks博士观察完金星凌日后,设计了一个复杂的电阻器。为了简化题目,题目中的常数与现实世界有所不同。 这个电阻器内有编号为 1∼n1∼n 的 nn 个独立水箱,水箱呈圆柱形,底面积为 1 m21 ...
  • CRZbulabula
  • CRZbulabula
  • 2017年01月09日 11:05
  • 453

UOJ164 V 线段树历史查询

题目:第一行两个数:n,m。接下来一行 n 个数,第 i个数表示初始时第i个水箱内有ai m3的水。接下来 m 行中,第 i行第一个数ti表示操作类型:若 ti=1,则接下来三个整数li,ri,xi,...
  • dy0607
  • dy0607
  • 2017年01月15日 20:46
  • 293

uoj#164. 【清华集训2015】V

传送门:http://uoj.ac/problem/164 思路:科学的题面: 请你写一个数据结构支持以下功能: 1:区间[l,r]加x 2:区间[l,r]减x并和0取max 3:区间覆盖 ...
  • thy_asdf
  • thy_asdf
  • 2016年04月26日 10:37
  • 540

#164. 【清华集训2015】V

线段树维护 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ...
  • sxb_201
  • sxb_201
  • 2016年03月13日 20:33
  • 311

UOJ164 V 线段树lazytag维护历史最值

题意:维护一列数,支持: 1.区间加A 2.区间减A,减法结束后每个位置与0取max 3.区间覆盖成A 4.询问单点当前值 5.询问单点历史最值线段树lazytag维护历史最值,要记录四个数...
  • Frods
  • Frods
  • 2017年01月15日 20:10
  • 459

线段树详解 (原理,实现与应用)

线段树详解 By 岩之痕 目录: 一:综述 二:原理 三:递归实现 四:非递归原理 五:非递归实现 六:线段树解题模型 七...
  • qq_16964363
  • qq_16964363
  • 2018年02月05日 13:52
  • 54

线段树难题--史上最大值nkoj3726

P3726史上最大值 时间限制 : - MS   空间限制 : 165536 KB   问题描述 给出一个长度为n的序列,一开始序列中每个数字都为0。现在有两种操作: 1.将区间[x,y]的数...
  • INCINCIBLE
  • INCINCIBLE
  • 2016年07月21日 20:48
  • 420

UOJ164 线段树历史最值查询

对于线段树的历史查询我们可以用一个二元组定义(a, b)表示+a对b取max 我们用二元组(a, b), (c, d)分别表示当前以及历史的标记; 注意顺序的问题很重要,提醒一下重载运算符会很方便...
  • accept_
  • accept_
  • 2017年02月24日 18:49
  • 101
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:UOJ164 V 线段树lazytag维护历史最值
举报原因:
原因补充:

(最多只允许输入30个字)