网上似乎这道题的题解很少?写一个吧

我跟这道题的渊源追溯到了上个学期刚刚学线段树的那一天。。。

当时线段树专题前边的题都是一些板子就不一会就水过了,然后就看到了最后一题的它:山海经

那一个上午,我竭尽全力,却毫无收获。

后来我下午继续肛还是肛不动,但是mikufun大神,在刚学线段树的阶段,把这道我现在都要写30min的难题给A了!

他当时的NB代码:

 #include<iostream>
#include<cstdio>
using namespace std;
struct tree{
int l,r,da,dam,dal,dar;
int lme,lmr,le,lr;
}t[];
void build(int l1,int r1,int k){
t[k].l=l1,t[k].r=r1;
if(l1==r1){
scanf("%d",&t[k].da);
t[k].dal=t[k].dam=t[k].dar=t[k].da;
t[k].le=t[k].lme=t[k].lmr=t[k].lr=l1;
return;
}
int mid=(l1+r1)/;
build(l1,mid,k*);
build(mid+,r1,k*+);
t[k].da=t[k*].da+t[k*+].da;
if(t[k*].dal>=t[k*].da+t[k*+].dal){
t[k].dal=t[k*].dal;
t[k].le=t[k*].le;
}
else{
t[k].dal=t[k*].da+t[k*+].dal;
t[k].le=t[k*+].le;
}
if(t[k*+].dar>t[k*+].da+t[k*].dar){
t[k].dar=t[k*+].dar;
t[k].lr=t[k*+].lr;
}
else{
t[k].dar=t[k*+].da+t[k*].dar;
t[k].lr=t[k*].lr;
}
if(max(t[k*].dam,max(t[k*+].dam,t[k*].dar+t[k*+].dal))==t[k*].dam){
t[k].dam=t[k*].dam;
t[k].lme=t[k*].lme;t[k].lmr=t[k*].lmr;
}
else if(max(t[k*].dam,max(t[k*+].dam,t[k*].dar+t[k*+].dal))==t[k*+].dam){
t[k].dam=t[k*+].dam;
t[k].lme=t[k*+].lme;t[k].lmr=t[k*+].lmr;
}
else if(max(t[k*].dam,max(t[k*+].dam,t[k*].dar+t[k*+].dal))==t[k*].dar+t[k*+].dal){
t[k].dam=t[k*].dar+t[k*+].dal;
t[k].lme=t[k*].lr;t[k].lmr=t[k*+].le;
}
}
inline int sea_qu(int l1,int r1,int k,int x,int &ll,int &rr){
if(l1<=t[k].l&&t[k].r<=r1){
if(!x){
ll=t[k].lme;rr=t[k].lmr;
return t[k].dam;
}
if(x==){
ll=t[k].lr;rr=t[k].r;
return t[k].dar;
}
if(x==){
ll=t[k].l;rr=t[k].le;
return t[k].dal;
}
}
int mid=(t[k].l+t[k].r)/,ans,a1,a2,a3,a4,a5,a6;
int a,b,c,d,e,g,h,z;
if(x==){
a1=sea_qu(l1,r1,k*+,,a,b);
ll=a;rr=t[k].r;
if(l1<=mid){
a5=sea_qu(l1,r1,k*,,b,c)+t[k*+].da;
if(a5>a1){
ll=b,rr=t[k].r;
return a5;
}
}
return a1;
}
if(x==){
a2=sea_qu(l1,r1,k*,,z,c);
rr=c;ll=t[k].l;
if(r1>mid){
a6=sea_qu(l1,r1,k*+,,b,z)+t[k*].da;
if(a6>a2){
ll=t[k].l,rr=z;
return a6;
}
}
return a2;
}
if(!x){
if(r1<=mid){
ans=sea_qu(l1,r1,k*,,ll,rr);
return ans;
}
if(l1>mid){
ans=sea_qu(l1,r1,k*+,,ll,rr);
return ans;
}
a1=sea_qu(l1,r1,k*,,a,b);
a2=sea_qu(l1,r1,k*+,,b,c);
a3=sea_qu(l1,r1,k*,,h,d);
a4=sea_qu(l1,r1,k*+,,e,g);
if(max(a1+a2,max(a3,a4))==a3){
ll=h,rr=d;
return a3;
}
if(max(a1+a2,max(a3,a4))==a1+a2){
ll=a;
rr=c;
return a1+a2;
}
if(max(a1+a2,max(a3,a4))==a4){
ll=e,rr=g;
return a4;
}
}
}
int main(){
int n,m,x,y,ll,rr;
scanf("%d%d",&n,&m);
build(,n,);
for(int i=;i<=m;i++){
scanf("%d%d",&x,&y);
int ans=sea_qu(x,y,,,ll,rr);
cout<<ll<<" "<<rr<<" "<<ans<<endl;
}
return ;
}

这可是在当时,也就是没有题能打50行+的时候啊。

我当时看到有人A了都惊呆了。

我就去问mikufun,然后他说:“自己再想一想。”

我后来就一直想A掉这道题,可总有一些理由阻挡我蹒跚前进的脚步。

但现在我终于A了,很轻松释然。

我记得当时老吕看只有mikufunA了这道题,鼓励我们:“没事,只要知识没有丢,这些题你们以后看都很简单的。”

可是我当时想:“这么难的题,我恐怕一辈子都做不对了。”没想到啊,才几个月,变化已经这么大了。

OI改变你我。

题解:线段树维护左端点开始的最大值,右端点开始的最大值,区间最大值,以及它们的端点。

在子树合并到父亲时,父亲左端点开始的最大值可以由左儿子左端点开始的最大值,左儿子全部值+右左端点开始的最大值来更新。

同理于父亲右端点开始的最大值,区间最大值。但区间最大值还能够由左儿子右端点的最大值+右儿子左端点的最大值来更新。

总体上细节挺多的,注意好它字典序问题。其实就是几个顺序的调整罢了。

在merge合并时,我为了之后的查询更加方便,选择了用结构体进行合并,因为在find查找时由于[a,b]区间会被分成log个区间,因此等效于在子树合并到父亲。

 #include<bits/stdc++.h>
#define N 100005
#define Inf 0x7f7f7f7f
#define lch k<<1
#define rch k<<1|1
inline int read(){
int x=,f=;char ch=getchar();
while(!isdigit(ch))f=(ch=='-'?-:),ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();
return x*f;
}
struct node{int l,r,mx,lmx,lp,rmx,rp,smx,slp,srp;}tr[N<<];
int n,m;
node merge(const node &t1,const node &t2){
node ret;ret.lmx=ret.rmx=ret.smx=-Inf;
ret.l=t1.l,ret.r=t2.r;ret.mx=t1.mx+t2.mx;
ret.lmx=t1.lmx,ret.lp=t1.lp;
ret.rmx=t2.rmx,ret.rp=t2.rp;
if(t1.smx>=t2.smx) ret.smx=t1.smx,ret.slp=t1.slp,ret.srp=t1.srp;
if(t1.rmx+t2.lmx>ret.smx) ret.smx=t1.rmx+t2.lmx,ret.slp=t1.rp,ret.srp=t2.lp;
if(t1.rmx+t2.lmx==ret.smx&&( (t1.rp<ret.slp) || (t1.rp==ret.slp && t2.lp<ret.srp) )) ret.smx=t1.rmx+t2.lmx,ret.slp=t1.rp,ret.srp=t2.lp;
if(t2.smx>ret.smx) ret.smx=t2.smx,ret.slp=t2.slp,ret.srp=t2.srp;
if(t1.mx+t2.lmx>ret.lmx) ret.lmx=t1.mx+t2.lmx,ret.lp=t2.lp;
if(t2.mx+t1.rmx>ret.rmx) ret.rmx=t2.mx+t1.rmx,ret.rp=t1.rp;
if(ret.smx<=ret.lmx) ret.slp=ret.l,ret.srp=ret.lp;
if(ret.smx<ret.rmx) ret.slp=ret.rp,ret.srp=ret.r;
return ret;
}
void build(int k,int l,int r){
tr[k].l=l,tr[k].r=r;
if(l==r){tr[k].mx=tr[k].lmx=tr[k].rmx=tr[k].smx=read();tr[k].lp=tr[k].rp=tr[k].slp=tr[k].srp=l;return;}
const int mid=(l+r)>>;
build(lch,l,mid),build(rch,mid+,r);
tr[k]=merge(tr[lch],tr[rch]);
}
node find(int k,int l,int r){
if(tr[k].l>=l&&tr[k].r<=r) return tr[k];
node ret;
if(l<=tr[lch].r&&r>=tr[rch].l) ret=merge(find(lch,l,r),find(rch,l,r));
else if(r<=tr[lch].r) ret=find(lch,l,r);
else if(l>=tr[rch].l) ret=find(rch,l,r);
return ret;
}
int main(){
n=read(),m=read();
build(,,n);
int a,b;
for(int i=;i<=m;++i){
a=read(),b=read();
node ret=find(,a,b);
printf("%d %d %d\n",ret.slp,ret.srp,ret.smx);
}
}

我的超短超帅代码

[COGS 755]山海经:线段树的更多相关文章

  1. COGS 577 蝗灾 线段树+CDQ分治

    第一次写cdq分治 感谢hhd&lty 这20亿对CP的指导(逃) 其实 就是 递归看左半部分对右半部分的贡献 (树状数组写挂了--临时改的线段树[大写的尴尬]) //By SiriusRen ...

  2. COGS 2638. 数列操作ψ 线段树

    传送门 : COGS 2638. 数列操作ψ 线段树 这道题让我们维护区间最大值,以及维护区间and,or一个数 我们考虑用线段树进行维护,这时候我们就要用到吉司机线段树啦 QAQ 由于发现若干次an ...

  3. cogs 2554. [福利]可持久化线段树

    题目链接 cogs 2554. [福利]可持久化线段树 题解 没有 代码 #include<cstdio> #include<cstring> #include<algo ...

  4. 【BZOJ 1901】Zju2112 Dynamic Rankings &&【COGS 257】动态排名系统 树状数组套线段树

    外面是树状数组,里面是动态开点线段树,对于查询我们先把有关点找出来,然后一起在线段树上行走,这样就是单个O(log2)的了 #include <cstdio> #include <v ...

  5. AC日记——[福利]可持久化线段树 cogs 2554

    2554. [福利]可持久化线段树 ★★☆   输入文件:longterm_segtree.in   输出文件:longterm_segtree.out   简单对比时间限制:3 s   内存限制:2 ...

  6. Cogs 1688. [ZJOI2008]树的统计Count(树链剖分+线段树||LCT)

    [ZJOI2008]树的统计Count ★★★ 输入文件:bzoj_1036.in 输出文件:bzoj_1036.out 简单对比 时间限制:5 s 内存限制:162 MB [题目描述] 一棵树上有n ...

  7. cogs 1361. 树 线段树

    1361. 树 ★   输入文件:treed.in   输出文件:treed.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 在一个凉爽的夏夜,xth和rabbit来到 ...

  8. cogs 247. 售票系统 线段树

    247. 售票系统 ★★☆   输入文件:railway.in   输出文件:railway.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 某次列车途经C个城市,城市 ...

  9. cogs 182. [USACO Jan07] 均衡队形 线段树

    182. [USACO Jan07] 均衡队形 ★★☆   输入文件:lineup.in   输出文件:lineup.out   简单对比时间限制:4 s   内存限制:128 MB 题目描述 农夫约 ...

随机推荐

  1. PyQt4 Python GUI窗体应用程序

    目录 目录 前言 软件环境 PyQT简介 Setup PyCharm Setup SIP Setup PyQt4 测试PyQt是否安装成功 常见错误 最后 前言 还是一句老话,公司要什么我就做什么.这 ...

  2. GitHub Port 443 Refused

    最近在本地Github上传和更新远程仓库的时候老是显示 GitHub - failed to connect to github 443 windows/ Failed to connect to g ...

  3. python3实现自动化框架robotframework(最新)

    # python3.6及以上版本兼容RIDE1.7.3版本由于最近RIDE1.7.3的版本改进,RIDE这个版本对高版本的wxpython兼容很好,python3.6及以上版本都可以顺利运行RIDE为 ...

  4. Django ModelChoiceField:过滤查询集并将默认值设置为对象

    我有一个Django Form类定义喜欢这个在Models: class AccountDetailsForm(forms.Form): ... adminuser = forms.ModelChoi ...

  5. [JavaScript] console.log只在查看时才会读取这个打印的对象,并把此刻相关属性和值显示出来

      /** * 写个函数解决console.log只在查看时才会读取这个打印的对象,并把此刻相关属性和值显示出来 * @param arg */ const log = function (...ar ...

  6. [Vuejs] 点击单选框触发两次点击事件的处理

    <el-radio-group v-model="uploadStatus" class="upload-status-radio"> <el ...

  7. (转).net中的session与cookies区别及使用方法

    cookie数据存放在客户的浏览器上,session数据放在服务器上,cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session   先介绍一 ...

  8. HttpServletResponse ServletResponse 返回响应 设置响应头设置响应正文体 重定向 常用方法 如何重定向 响应编码 响应乱码

    原文地址:HttpServletResponse ServletResponse 返回响应 设置响应头设置响应正文体 重定向 常用方法 如何重定向 响应编码 响应乱码 HttpServletRespo ...

  9. 思考--mysql 分库分表的思考

    查询不在分库键上怎么办,扫描所有库?由于分库了,每个库扫描很快?所以比单个表的扫描肯定快,可以这样理解吗. 多表jion怎么弄,把内层表发给每个分库吗? citus,tidb 都有这些问题,citus ...

  10. MySQL 用 limit 为什么会影响性能?

    一,前言 首先说明一下MySQL的版本: mysql> select version();+-----------+| version() |+-----------+| 5.7.17 |+-- ...