经典线段树 UVALive 3938/UVA 1400
题意:就是相当于动规里面的求最大连续子串,不同的是,这里需要读入一个区间x,y,输出的区间 a,b 且x<=a<=b<=y,使得a b的连续子串最长,而且询问次数达到了10的五次方。
我是在大白书上看到这个题,一开始想简单了,就照着刘汝佳的思路写,线段树里只存了前缀最大和,后缀最大和,总最大和,但题目要求输出区间,明显的需要添加记录维护区间位置的,而且不止要存储 a,b,还要存pre suf,前缀 后缀的边界位置。我第一次写的时候意识到了,但是那个时候已经有点混乱了,我以为在查询的时候,根据最大和就能确定区间。。。结果真是。。。智商被碾压。
还有个令人心酸的地方,直接导致我WA了整整一版,。。。尼玛,我记得校队选拔赛的时候也是同样的问题卡了我最后一个简单的题目,就是我用的中间变量暂存最大和,我知道最大和肯定会超过int,所以之前就设置了ll,但尼玛我定义中间变量的时候,居然下意识还是用的int。。。。。检查了我N多遍才查出来。。尼玛太心酸了。。一定要注意细节
#include <iostream>
#include <cstdio>
#include <cstring>
#define Lson x<<1,l,mid
#define Rson (x<<1|1),mid+1,r
#define N 500030
using namespace std; struct node//线段树节点只需要记录前缀最右边间位置pre,类似的后缀suf,以及真正的解区间,vx,vy
{
int vx,vy;
int suf,pre;
} tree[N*];
long long s[N];
void getup(int x,int l,int r)
{
if (s[tree[x<<].pre]-s [l-]>=s[tree[x<<|].pre]-s[l-]){
tree[x].pre=tree[x<<].pre;
}
else{
tree[x].pre=tree[x<<|].pre;
}
if (s[r]-s[tree[x<<].suf-]>=s[r]-s[tree[x<<|].suf-]){
tree[x].suf=tree[x<<].suf;
}
else{
tree[x].suf=tree[x<<|].suf;
}
long long v1=s[tree[x<<].vy]-s[tree[x<<].vx-];
long long v2=s[tree[x<<|].vy]-s[tree[x<<|].vx-];
long long v0=s[tree[x<<|].pre]-s[tree[x<<].suf-];
if (v1>=v2){
tree[x].vx=tree[x<<].vx;
tree[x].vy=tree[x<<].vy;
}
else{
tree[x].vx=tree[x<<|].vx;
tree[x].vy=tree[x<<|].vy;
}
if (v0==s[tree[x].vy]-s[tree[x].vx-]){
if (tree[x<<].suf<tree[x].vx){
tree[x].vx=tree[x<<].suf;
tree[x].vy=tree[x<<|].pre;
}
else if (tree[x<<].suf==tree[x].vx && tree[x<<|].pre<tree[x].vy){
tree[x].vy=tree[x<<|].pre;
}
}
if (v0>s[tree[x].vy]-s[tree[x].vx-]){
tree[x].vx=tree[x<<].suf;
tree[x].vy=tree[x<<|].pre;
} }
void build(int x,int l,int r)
{
if (l==r)
{
tree[x].pre=tree[x].suf=tree[x].vy=tree[x].vx=l;
return;
}
int mid=(l+r)/;
build(Lson);
build(Rson);
getup(x,l,r);
}
node query(int st,int e,int x,int l,int r)
{
if (st<=tree[x].vx && tree[x].vy<=e){
return tree[x];
}
int mid=(l+r)/;
if (st>mid){
return query(st,e,Rson);
}
if (e<=mid){
return query(st,e,Lson);
}
node a=query(st,e,Lson);
node b=query(st,e,Rson);
node c;
if (s[a.vy]-s[a.vx-]>=s[b.vy]-s[b.vx-]){
c.vx=a.vx;
c.vy=a.vy;
}
else {
c.vx=b.vx;
c.vy=b.vy;
}
if (s[a.pre]-s[st-]>=s[b.pre]-s[st-]){
c.pre=a.pre;
}
else{
c.pre=b.pre;
}
if (s[e]-s[a.suf-]>=s[e]-s[b.suf-]){
c.suf=a.suf;
}
else{
c.suf=b.suf;
}
if (s[b.pre]-s[a.suf-]==s[c.vy]-s[c.vx-]){
if (a.suf<c.vx){
c.vx=a.suf;
c.vy=b.pre;
}
if (a.suf==c.vx && b.pre<c.vy){
c.vy=b.pre;
}
}
else
if (s[b.pre]-s[a.suf-]>s[c.vy]-s[c.vx-]){
c.vx=a.suf;
c.vy=b.pre;
}
return c;
}
int main()
{
int n,m;
int counts=;
while (scanf("%d%d",&n,&m)!=EOF)
{
int i,j,k;
memset(s,,sizeof s);
long long tt;
for (i=;i<=n;i++){
scanf("%lld",&tt);
s[i]=s[i-]+tt;
}
build(,,n);
printf("Case %d:\n",++counts);
for (i=;i<=m;i++){
int ss,e;
scanf("%d%d",&ss,&e);
node ans=query(ss,e,,,n); printf("%d %d\n",ans.vx,ans.vy);
}
}
return ;
}
经典线段树 UVALive 3938/UVA 1400的更多相关文章
- ZOJ - 1610 经典线段树染色问题
这个是一个经典线段树染色问题,不过题目给的是左右左右坐标,即[0,3]包含0-1这一段 1-2这一段 2-3这一段,和传统的染色不太一样,不过其实也不用太着急. 我们把左边的坐标+1,即可,那么[0, ...
- pku 2777(经典线段树染色问题)
Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 41202 Accepted: 12458 Des ...
- poj-2828 Buy Tickets(经典线段树)
/* Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 10207 Accepted: 4919 Descr ...
- poj 2528 poster经典线段树+lazy+离散化
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; ; #def ...
- ZOJ1610(经典线段树涂色问题)
Description Painting some colored segments on a line, some previously painted segments may be covere ...
- poj Hotel 线段树
经典线段树的题. 每个节点存储的信息:左端点连续空房间的长度,右端点连续空房间长度,连续空房间的最大长度. 由于要求每次必须从尽量靠左边的位置进行居住,那么搜索时应尽量让区间起始位置更小: 1.如果当 ...
- 『zkw线段树及其简单运用』
阅读本文前,请确保已经阅读并理解了如下两篇文章: 『线段树 Segment Tree』 『线段树简单运用』 引入 这是一种由\(THU-zkw\)大佬发明的数据结构,本质上是经典的线段树区间划分思想, ...
- 线段树模板hdu 1166:敌兵布阵
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 线段树模板hdu 1754:I Hate It
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
随机推荐
- navicat报错2005 - Unknown MySQL server host 'localhost' (0) 原因及解决方法
报错原因:没有连接互联网,用navicat连接本地mysql数据库,连接属性ip为localhost. 解决办法:将ip改为127.0.0.1即可.localhost是需要DNS解析后才会是127.0 ...
- 嵊州普及Day2T2
题意:对于n个数的数列,进行排列,求第m个大于此数列的数列. 思路:查找后2个是否逆序,若是,将后3个递归.如此运算,找后面大于此数中最小数交换,然后将后面数列顺序排列. 相对简单. 见代码: #in ...
- 杂记 -- 关于ref、kepp-alive、nextTick、fetch
1.ref:定义一个普通的dom节点或一个vue的组件实例对象 定义方法: <div class="page1"> <button @click="li ...
- Java多线程涉及的概念(3)
Java多线程涉及的概念 在理解进程和线程概念之前首选要对并发有一定的感性认识,如果服务器同一时间内只能服务于一个客户端,其他客户端都再那里傻等的话,可见其性能的低下估计会被客户骂出翔来,因此并发编程 ...
- 3. SSH 服务器安装
1.查看SSH是否安装(检查是否装了SSH包) 输入命令:rpm -qa | grep ssh 2.安装SSH 服务 yum install openssh-server 3.查看SSH服务是否正在运 ...
- 修改ssh主机名
三台机器的配置相似,以zk1为例 1.修改hostname vi /etc/hostname zk1 2.修改hosts文件 vi /etc/hosts 10.45.48.233 zk1 10.45. ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 命名空间
假设这样一种情况,当一个班上有两个名叫 Zara 的学生时,为了明确区分它们,在使用名字之外,不得不使用一些额外的信息,比如他们的家庭住址,或者他们父母的名字等等. 同样的情况也出现在 C++ 应用程 ...
- vue学习(十二)vue全家桶 Vue-router&Vuex
一 vue-router的安装 二 vue-router的基本使用 三 命名路由 四 动态路由的匹配和路由组件的复用 一 vue-router的安装 NPM npm install vue-route ...
- 使用apply调用函数
实现函数 calllt,调用之后满足如下条件1.返回的结果为调用fn之后的结果2.fn的调用为calllt的第一个参数之后的全部参数 方法1 使用es6 function calllt(...para ...
- UVA - 10003 Cutting Sticks(切木棍)(dp)
题意:有一根长度为L(L<1000)的棍子,还有n(n < 50)个切割点的位置(按照从小到大排列).你的任务是在这些切割点的位置处把棍子切成n+1部分,使得总切割费用最小.每次切割的费用 ...