题目描述

在人气动漫 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. vue中使用对非表单元素使用contenteditable的问题

    先说下问题,再上解决方案: span编辑时有多余空格和回车会影响样式(我用的是span便以此为例) 代码:(有换行符) 效果图: 代码:(无换行符) 效果图: 当在span标签的contentedit ...

  2. 转 Oracle]如何在Oracle中设置Event

    https://www.cnblogs.com/gaojian/p/7619960.html 为了调查Oracle 的故障,可以通过设置event ,来了解详细的状况.方法如下: ■ 如果使用 SPF ...

  3. Python学习 day04

    一.list list可以存放各种类型的数据,与java中list类差不多,比如li = ['keith', 1, True, [1, 2, 3], {name: 'tangtang', age: 1 ...

  4. CenctOS6 and CenctOS7 多种姿势解决忘记密码

    -----linux---- 忘记密码啦!!! 忘记密码教程!!! 教你们忘记密码(我原来密码就是123456,忘记是不可能的!假装忘记的样子 0.0) 现在我们忘记密码了!对忘记密码了.我忘记密码了 ...

  5. zabbix 千台服务器自动添加实战

    一,模式   zabbix 的自动添加 主机有梁祝方式: 自动发现-----被动模式 由服务端主动发起,Zabbix Server开启发现进程,定时扫描局域网中IP服务器.设备, 自动注册----主动 ...

  6. 如何将项目部署到远程的Linux机器上的tomcat上

    下面来练习一下如何将本地的一个项目部署到远程的Linux机器上去. 第一步:将要部署到Linux机器上的项目打成一个war包 war包有一个好处tomcat可以自动解压 第二步:将打好的war上传到L ...

  7. 【Java】使用Eclipse进行远程调试,Linux下开启远程调试

    原博地址:http://blog.csdn.net/dfdsggdgg/article/details/50730311 1.center下,在startup.sh文件首行中添加如下语句 declar ...

  8. 浅谈辄止WCF:完成最基本的WCF项目(1)

    Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Windows 通讯开发平台. WCF的所有服务都会公开契约.契约包 ...

  9. [Scala] Currying

    Currying是一種函數式編程技巧, 指的是把接受多個參數的函數變換成接受一個單一參數的函數. 以一個簡單的例子在Scala中實現.. def f(a:Int, b:Int)={ a+b } //f ...

  10. Node.js 框架对比之 Express VS Koa

    背景 上图是一个典型的采用 Node.js 开发 web 应用的前后端结构,下面介绍一下 Node 服务层在其中的作用以及使用 Node.js 的一些优劣. Node 服务层作用: 请求代理 传统做法 ...