题目描述

在人气动漫 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. windows同时安装python2和python3两个版本

    1.安装python2 下载地址: https://www.python.org/downloads/windows/ 进入页面,下拉,64位系统要选择这个. 下载完成后,一直点击下一步,直到安装完毕 ...

  2. shell 操作符详解

     = 赋值操作符,可以用于算术和字符串赋值 +  加法计算   -  减法运算 *  乘法运算 /   除法运算 **  幂运算 % 模运算 取他除后的剩余数   因此这个十分好求公约数 += &qu ...

  3. elastic 集群安装

    Elastic Search 安装和配置 1.下载 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6. ...

  4. Java基础23-main方法

    /* 主函数(主方法) 1.public(访问修饰符,公共的)代表类或者该函数访问权限是最大的 2.static 代表主函数随着类的加载就已经存在了 3.void 代表主函数没有具体的返回值 4.ma ...

  5. unity文件 PlayerPrefs.SetInt 保存 And PlayerPrefs.GetInt读取

    unity文件保存读取PlayerPrefs.SetInt   And  PlayerPrefs.GetInt using UnityEngine; using System.Collections; ...

  6. BFC --- Block Formatting Context --- 块级格式化上下文

    虽然知道块级格式化上下文是什么东西,但要我把这个东西给说清楚,还真的不是一件容易的事儿,所以这篇文章我就要说说清楚到底什么使传说中的BFC,即块级格式化上下文. 一.BFC的通俗理解 通俗的理解 -- ...

  7. Git~分支真的很轻

    轻,让人觉得很爽 所有源代码管理工具都有管理分支的功能,git当然也不例外,而且git的分支是非常轻的,不像tfs,svn那样,复制一大堆代码,git只记录变化的内容,有本地分支与远程分支之分,原则上 ...

  8. Java学习第二十五天

    1:如何让Netbeans的东西Eclipse能访问. 在Eclipse中创建项目,把Netbeans项目的src下的东西给拿过来即可. 注意:修改项目编码为UTF-8 2:GUI(了解) (1)用户 ...

  9. Android的存储方式

    Android常见的四种存储方式: 1. SharePreference 2. File 3. ContentProvider 4. SQLite 第一种: 保存在应用程序私有的文件夹下---- 只有 ...

  10. RequireJS 2.0 正式发布

    就在前天晚上RequireJS发布了一个大版本,直接从version1.0.8升级到了2.0.随后的几小时James Burke又迅速的将版本调整为2.0.1,当然其配套的打包压缩工具r.js也同时升 ...