题目描述

在人气动漫 Black Rock shooter 中,当加贺里对麻陶 说出了“滚回去“以后,与此同时,在另一个心灵世界里, BRS 也遭到了敌人的攻击。此时,一共有 n 个攻击排成一行 朝着她飞了过来,每个攻击有一个伤害值。并且每个攻击伤 害可能随时变化。BRS 的攻击可以打掉一段连续的攻击。现 在,给出 m 段攻击,求出 BRS 最多可以打掉此段里多少的 伤害(就是说从给定一段里选择连续一段打掉)。伤害从 1 到 n 编号。

输入输出格式

输入格式:

第一行 2 个整数:n , m

第二行 n 个数:第 i 个数代表第 i 个攻击

第 3 到 2+m 行:每行三个数 k,x,y。若 k=1,x,y 代表查询的区间。若 k=2,代表第 x 个攻击伤害改为了 y 所有的伤害值绝对值<=1000

输出格式:

对于每次 k=1,输出一个整数代表最大值

题解

有题目可知这道题要求最大区间子段和,考虑用线段树维护。

对于线段树的每个节点,我们要储存四个信息:

 

typedef struct Node
{
int l, r;
long long lsum, rsum, msum, sum;
//lsum:从左边开始的最长子段和
//rsum:从右边开始的最长子段和
//msum:整个区间中的最长子段和
//sum:整个区间的子段和
Node *lson, *rson;
Node(): l(), r(), lsum(), rsum(), msum(), lson(NULL), rson(NULL), sum() {}
int len() {return r - l;}
int mid() {return (l + r) >> ;}
}node, *pointer;

对于每个变量,我们要在PushUp操作中进行维护:

void PsuhUp(pointer rt)
{
rt->sum = rt->lson->sum + rt->rson->sum;
        //和的维护是直接维护
rt->lsum = std::max(rt->lson->lsum, rt->lson->sum + rt->rson->lsum);
        //从左边开始的最长子段和有可能就是左边的最长子段和也有可能是整个左子树加上右子树的左边最长子段和
rt->rsum = std::max(rt->rson->rsum, rt->rson->sum + rt->lson->rsum);
        //右边同理
rt->msum = std::max(rt->lson->rsum + rt->rson->lsum, std::max(rt->lson->msum, rt->rson->msum));
        //中间的最长子段和除了要比较左右子树的两个之外,还要考虑将两个子树区间合并后新产生的的一个子段
}

最麻烦的是查询操作,同样也分为两种情况:

  一种是在一个区间的中间的最长子段和,一种是有两个子树的左右最长子段和拼起来的。

//前面两个query操作是为了考虑第二种情况 
LL QueryR(pointer rt, LL x, LL y)
{
if(rt->l >= x && y >= rt->r) return rt->rsum;
LL ans = QueryR(rt->rson, x, y);
if(x < rt->mid()) ans = std::max(ans, QueryR(rt->lson, x, y) + rt->rson->sum);
return ans;
} LL QueryL(pointer rt, LL x, LL y)
{
if(rt->l >= x && y >= rt->r) return rt->lsum;
LL ans = QueryL(rt->lson, x, y);
if(y > rt->mid()) ans = std::max(ans, QueryL(rt->rson, x, y) + rt->lson->sum);
return ans;
} LL Query(pointer rt, LL x, LL y)
{
if(x <= rt->l && rt->r <= y) return rt->msum;
LL ans = -0x7fffffff;
if(y <= rt->mid()) ans = Query(rt ->lson, x, y); //整个区间都在左子树上
else if(x >= rt->mid()) ans = Query(rt->rson, x, y);   //整个区间都在右子树上
else ans = std::max(QueryR(rt->lson, x, y) + QueryL(rt->rson, x, y), std::max(Query(rt->lson, x, y), Query(rt->rson, x, y)));
                        //区间分布在左右子树上
return ans;
}

代码

#include <bits/stdc++.h>
using namespace std;
#define LL long long const int MAX = ;
typedef struct Node
{
int l, r;
long long lsum, rsum, msum, sum;
Node *lson, *rson;
Node(): l(), r(), lsum(), rsum(), msum(), lson(NULL), rson(NULL), sum(NULL) {}
int len() {return r - l;}
int mid() {return (l + r) >> ;}
}node, *pointer; class Segement_Tree
{
private:
void PsuhUp(pointer rt)
{
rt->sum = rt->lson->sum + rt->rson->sum;
rt->lsum = max(rt->lson->lsum, rt->lson->sum + rt->rson->lsum);
rt->rsum = max(rt->rson->rsum, rt->rson->sum + rt->lson->rsum);
rt->msum = max(rt->lson->rsum + rt->rson->lsum, max(rt->lson->msum, rt->rson->msum));
} LL QueryR(pointer rt, LL x, LL y)
{
if(rt->l >= x && y >= rt->r) return rt->rsum;
LL ans = QueryR(rt->rson, x, y);
if(x < rt->mid()) ans = max(ans, QueryR(rt->lson, x, y) + rt->rson->sum);
return ans;
} LL QueryL(pointer rt, LL x, LL y)
{
if(rt->l >= x && y >= rt->r) return rt->lsum;
LL ans = QueryL(rt->lson, x, y);
if(y > rt->mid()) ans = max(ans, QueryL(rt->rson, x, y) + rt->lson->sum);
return ans;
} public:
pointer root = new Node();
LL a[MAX]; void Build(pointer rt, int l, int r)
{
rt->r = r, rt->l = l;
if(r - l == )
{
rt->lsum = a[l], rt->rsum = a[l], rt->msum = a[l], rt->sum = a[l];
return ;
}
rt->lson = new Node(), rt->rson = new Node();
Build(rt->lson, l, rt->mid()), Build(rt->rson, rt->mid(), r);
PsuhUp(rt);
return ;
} void Updata(pointer rt, LL x, LL y)
{
if(rt->r - rt->l == && rt->l == x)
{
rt->lsum = y, rt->rsum = y, rt->msum = y, rt->sum = y;
return ;
}
if(x < rt->mid()) Updata(rt->lson, x, y);
else Updata(rt->rson, x, y);
PsuhUp(rt);
} LL Query(pointer rt, LL x, LL y)
{
if(x <= rt->l && rt->r <= y) return rt->msum;
LL ans = -0x7fffffff;
if(y <= rt->mid()) ans = Query(rt ->lson, x, y);
else if(x >= rt->mid()) ans = Query(rt->rson, x, y);
else ans = max(QueryR(rt->lson, x, y) + QueryL(rt->rson, x, y), max(Query(rt->lson, x, y), Query(rt->rson, x, y)));
return ans;
}
}; Segement_Tree tree; inline long long Qread()
{
long long x = ; int w = ; char ch = getchar();
for(;!isdigit(ch); w |= (ch == '-'), ch= getchar());
for(;isdigit(ch);x = (x << ) + (x << ) + (ch ^ ), ch = getchar());
return w ? -x : x;
} inline int qread()
{
int x = ; int w = ; char ch = getchar();
for(;!isdigit(ch); w |= (ch == '-'), ch= getchar());
for(;isdigit(ch);x = (x << ) + (x << ) + (ch ^ ), ch = getchar());
return w ? -x : x;
} int main()
{
// freopen("BRS.in", "r", stdin);
// freopen("BRS.out", "w", stdout); int n, m;
LL opt, x, y;
memset(tree.a, , sizeof(tree.a));
scanf("%d%d", &n, &m);
for(int i = ; i <= n; ++ i) tree.a[i] = Qread();
tree.Build(tree.root, , n + );
for(int i = ; i <= m; ++ i)
{
opt = Qread(), x = Qread(), y = Qread();
if(opt == ) printf("%lld\n", tree.Query(tree.root, x, y + ));
if(opt == ) tree.Updata(tree.root, x, y);
}
}

Black Rock Shooter 题解的更多相关文章

  1. Black Rock Shooter

    在人气动漫 Black Rock shooter 中,当加贺里对麻陶 说出了"滚回去"以后,与此同时,在另一个心灵世界里, BRS 也遭到了敌人的攻击.此时,一共有 n 个攻击排成 ...

  2. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

  3. 【题解】CF1426E Rock, Paper, Scissors

    题目戳我 \(\text{Solution:}\) 考虑第二问,赢的局数最小,即输和平的局数最多. 考虑网络流,\(1,2,3\)表示\(Alice\)选择的三种可能性,\(4,5,6\)同理. 它们 ...

  4. Codeforces Round #672 (Div. 2) B. Rock and Lever题解(思维+位运算)

    题目链接 题目大意 给你一个长为n(n<=1e5)的数组,让你求有多少对a[i]和a[j] (i!=j)满足a[i]&a[j]>a[i]^a[j] 题目思路 这些有关位运算的题目肯 ...

  5. 题解 CF1426E - Rock, Paper, Scissors

    一眼题. 第一问很简单吧,就是每个 \(\tt Alice\) 能赢的都尽量让他赢. 第二问很简单吧,就是让 \(\tt Alice\) 输的或平局的尽量多,于是跑个网络最大流.\(1 - 3\) 的 ...

  6. CF1225E题解 Rock Is Push

    在打CF的时候没想到www这个dp真的蛮巧妙的 这是一道dp题(废话 假设我们走到了\((i,j)\)位置,因为我们只能下移/右移,那么我们所有上方与左方的石块(即\(\{ (i,j)|i<n ...

  7. POJ - 2339 Rock, Scissors, Paper

    初看题目时就发了个错误,我因为没有耐心看题而不了解题目本身的意思,找不到做题的突破口,即使看了一些题解,还是没有想到方法. 后来在去问安叔,安叔一语道破天机,问我有没有搞清题目的意思,我才恍然大悟,做 ...

  8. 2016 ACM/ICPC Asia Regional Qingdao Online(2016ACM青岛网络赛部分题解)

    2016 ACM/ICPC Asia Regional Qingdao Online(部分题解) 5878---I Count Two Three http://acm.hdu.edu.cn/show ...

  9. 2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 H题 Rock Paper Scissors Lizard Spock.(FFT字符串匹配)

    2018 ACM-ICPC 中国大学生程序设计竞赛线上赛:https://www.jisuanke.com/contest/1227 题目链接:https://nanti.jisuanke.com/t ...

随机推荐

  1. 常用维护SQL-数据清理

    truncate某个库的表数据 show full processlist; select concat('truncate table ',table_schema,'.',table_name,' ...

  2. zookeeper+dubbo简单部署方案

    1.zookeeper服务 首先,我们需要下载:zookeeper-3.4.9 解压后,在conf文件夹中添加一个配置文件zoo.cfg,内容如下: tickTime=2000 dataDir=/Us ...

  3. protobuf参考

    https://www.cnblogs.com/chenyangyao/p/5422044.html

  4. linux命令之find

    find find命令的格式:find [-path……] -options [-print -exec -ok] path:要查找的目录路径.       ~ 表示$HOME目录       . 表 ...

  5. oem的使用

    1 浏览器输入下面的网址: 虚拟机[安装orcale的机器]:http://localhost:1158/em/ 本机:http://192.168.47.10:1158/em/ 192.168.47 ...

  6. shell中if的可判断的类型

    -d :判断制定的是否为目录-z:判断制定的变量是否存在值-f:判断制定的是否为文件-L:判断制定的是否为符号链接-r:判断制定的是否可读-w:判断制定的是否可写-x:判断存在的对象是否可以执行!:测 ...

  7. AI从入门到放弃:CNN的导火索,用MLP做图像分类识别?

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:郑善友 腾讯MIG后台开发工程师 导语:在没有CNN以及更先进的神经网络的时代,朴素的想法是用多层感知机(MLP)做图片分类的识别:但 ...

  8. CentOS 下 安装 JDK8

    1.下载 在 /usr/local 目录下创建目录 java # cd /usr/local # mkdir java 登录网址:http://www.oracle.com/technetwork/j ...

  9. 网页设计,Access入门 2010,语文

    Access入门 2010(select查询) order by(按升序排列)?+desc(按降序排列) group by(进行分组,下一行只能用having) sum(数值总数)?+as?(新字段的 ...

  10. ActiveReport报表更改连接字符串及参数

    PageReport pr = new PageReport (new FileInfo("报表路径")); //报表路径如../Order/OrderSale.rdlx if(p ...