线段树

先看前三个操作,都是区间修改,我们对于信息维护一个二元组(a,b),表示x=max(x+a,b),那么第一个操作就是(a,-inf),第二个是(-a,0),第三个是(-inf,a)

然后看查询,第一个就是维护所有信息,那么考虑合并标记,(a,b)=(max(a1+a2,-inf),max(max(b1+a2,-inf),b2)),这里和-inf取max是为了防止溢出

然后是最后一个查询,其实就是相当于最大前缀和,那么我们考虑维护这个东西,每次下来标记,设为(f,g),f是父节点的最大子段和,g是总和,那么ff=max(max(ff->a,tt->a+f->a,max(tt->b,f->b)),就是可以取原来的和原来的和加上新的操作,可以取max,因为我们希望的是最大值。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 + ;
const ll inf = 1e16;
inline ll rd()
{
ll x = , f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = x * + c - ''; c = getchar(); }
return x * f;
}
int n, m;
ll a[N];
struct node {
ll A, B;
node() { A = ; B = -inf; }
node(ll _, ll __) : A(_), B(__) {}
node friend max(const node &a, const node &b) {
return node(max(a.A, b.A), max(a.B, b.B));
}
node friend operator + (const node &a, const node &b) {
return node(max(a.A + b.A, -inf), max(max(a.B + b.A, -inf), b.B));
}
bool Null()
{
return A == && B == -inf;
}
} T[N << ], F[N << ];
void paint(int x, node f, node t)
{
F[x] = max(F[x], T[x] + f);
T[x] = T[x] + t;
}
void pd(int x)
{
if(F[x].Null() && T[x].Null()) return;
paint(x << , F[x], T[x]);
paint(x << | , F[x], T[x]);
F[x] = T[x] = node(, -inf);
}
void modify(int l, int r, int x, int a, int b, node t)
{
if(l > b || r < a) return;
if(l >= a && r <= b)
{
paint(x, t, t);
return;
}
pd(x);
int mid = (l + r) >> ;
modify(l, mid, x << , a, b, t);
modify(mid + , r, x << | , a, b, t);
}
int query(int l, int r, int x, int p)
{
if(l == r) return x;
pd(x);
int mid = (l + r) >> ;
if(p <= mid) return query(l, mid, x << , p);
else return query(mid + , r, x << | , p);
}
int main()
{
n = rd();
m = rd();
for(int i = ; i <= n; ++i) a[i] = rd();
while(m--)
{
int opt = rd(), l, r, x;
if(opt == )
{
l = rd();
r = rd();
x = rd();
modify(, n, , l, r, node(x, -inf));
}
if(opt == )
{
l = rd();
r = rd();
x = rd();
modify(, n, , l, r, node(-x, ));
}
if(opt == )
{
l = rd();
r = rd();
x = rd();
modify(, n, , l, r, node(-inf, x));
}
if(opt == )
{
l = rd();
x = query(, n, , l);
printf("%lld\n", max(a[l] + T[x].A, T[x].B));
}
if(opt == )
{
l = rd();
x = query(, n, , l);
printf("%lld\n", max(a[l] + F[x].A, F[x].B));
}
}
return ;
}

bzoj5117的更多相关文章

随机推荐

  1. iOS开发:Toast for iPhone

    iOS开发:Toast for iPhone   分享一个我写的类似于android的toast的提示框 主要特点: 1,支持屏幕Y轴任意位置显示,设置距离顶/底端距离 2,支持多行文本 3,支持设置 ...

  2. 神经网络实现Discuz验证码识别

    最近自己尝试了网上的验证码识别代码项目,该小项目见以下链接: https://cuijiahua.com/blog/2018/01/dl_5.html 数据也就用了作者上传的60000张Discuz验 ...

  3. switch中的case不加break执行情况

    输出结果:230 分析,switch先匹配一个case满足$a,然后执行case里面的语句,直到遇到break,否则一直往下执行 <?php $a = ; switch($a){ : echo ...

  4. “ 不确定 "限制值的使用

    前言 前篇文章解释了限制值的五种类型以及获取它们的方法.但是对于其中可能不确定的类型( 45类型 ),当限制值获取函数返回-1的时候,我们无法仅通过这个函数返回值-1来判断是限制值获取失败还是限制值是 ...

  5. RabbitMQ 基础

    Windows下安装RabbitMq 下载RabbitMq 安装参考 http://www.rabbitmq.com/install-windows.html 下载Erlang Erlang 下载安装 ...

  6. c/c++预处理命令#pragma

    1 #pragma pack(push, 1)和#pragma pack(pop) #pragma pack用于指定数据在内存中的对齐方式.如果不指定对齐方式的话,默认为自然对齐. 1.1 #prag ...

  7. IDEA eclipse 控制台日志输出到文件

    eclipse IDEA

  8. undefined reference to '__android_log_print'解决方案

    1:在源程序中添加头文件 #include <cutils/log.h> 2:在Android.mk中添加 LOCAL_SHARED_LIBRARIES := \ libutils \ l ...

  9. linux内核驱动中对文件的读写 【转】

    本文转载自:http://blog.chinaunix.net/uid-13059007-id-5766941.html 有时候需要在Linux kernel--大多是在需要调试的驱动程序--中读写文 ...

  10. C++模板(二)【转】

    本文转自:http://www.cnblogs.com/gw811/archive/2012/10/25/2738929.html C++模板 模板是C++支持参数化多态的工具,使用模板可以使用户为类 ...