【SP1043】GSS1 - Can you answer these queries I

Description

给出了序列\(A_1,A_2,…,A_n\)。 \(a_i \leq 15007,1 \leq n \leq 50000\)。查询定义如下: 查询\((x,y)=max{a_i+a{i+1}+...+a_j;x \leq i \leq j \leq y }\)。 给定M个查询,程序必须输出这些查询的结果。

Input

  • 输入文件的第一行包含整数\(n\)。
  • 在第二行,\(n\)个数字跟随。
  • 第三行包含整数\(m\)。
  • \(m\)行跟在后面,其中第\(1\)行包含两个数字\(x_i\)和\(y_i\)。

Output

您的程序应该输出\(m\)查询的结果,每一行一个查询。

线段树维护最大子段和裸题.

直接把我的另一篇博客粘过来

数组定义

\(lsum[ ]\)代表 该区间左端点开始的最大连续和.

\(rsum[ ]\)代表 该区间右端点开始的最大连续和.

\(ssum[ ]\)代表 区间内最大连续和.

\(sum[ ]\) 代表区间和.

Que and A

Q:已知一个区间的左右区间的最大连续和,如何合并?

A:这个区间的最大连续和要么是左子区间的最大连续和,要么是右子区间的最大连续和.

要么是左子区间的最大右起子段和+右子区间的最大左起字段和.

code:\(ssum[o]=max(max(ssum[lson],ssum[rson]),rsum[lson]+lsum[rson])\)

Q:如何更新区间最大左起子段和.

A:新区间的最大左起子段和.要么是其左子区间最大连续和,要么是其左子区间和+右子区间的左起子段和.

最大右起子段和同理

code:\(lsum[o]=max(lsum[lson],sum[lson]+lsum[rson])\)

     \(rsum[o]=max(rsum[rson],sum[rson]+rsum[lson])\)

更新操作类似单点修改

代码中是结构体写法.

当两端不在左子节点或者右子节点的话,需要考虑合并的

代码

#include<cstdio>
#include<iostream>
#include<cctype>
#define ls o<<1
#define rs o<<1|1
#define R register
using namespace std;
inline void in(int &x)
{
    int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}
struct cod{int l,r,lsum,rsum,sum,ssum;}tr[50008*40];
inline void up(int o)
{
    tr[o].sum=tr[ls].sum+tr[rs].sum;
    tr[o].ssum=max(max(tr[ls].ssum,tr[rs].ssum),tr[ls].rsum+tr[rs].lsum);
    tr[o].lsum=max(tr[ls].lsum,tr[ls].sum+tr[rs].lsum);
    tr[o].rsum=max(tr[rs].rsum,tr[ls].rsum+tr[rs].sum);
}
void build(int o,int l,int r)
{
    tr[o].l=l;tr[o].r=r;
    if(l==r)
    {
        in(tr[o].sum);
        tr[o].lsum=tr[o].rsum=tr[o].ssum=tr[o].sum;
        return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    up(o);
}
cod query(int o,int x,int y)
{
    if(tr[o].l>=x and y>=tr[o].r) return tr[o];
    int mid=(tr[o].l+tr[o].r)>>1;
    if(y<=mid) return query(ls,x,y);
    if(x>mid) return query(rs,x,y);
    else
    {
        cod t,t1=query(ls,x,y),t2=query(rs,x,y);
        t.lsum=max(t1.lsum,t1.sum+t2.lsum);
        t.rsum=max(t2.rsum,t2.sum+t1.rsum);
        t.ssum=max(max(t1.ssum,t2.ssum),t1.rsum+t2.lsum);
        return t;
    }
}
int n,m;
int main()
{
    in(n);
    build(1,1,n);
    in(m);
    for(R int l,r;m;m--)
    {
        in(l),in(r);
        if(l>r)swap(l,r);
        printf("%d\n",query(1,l,r).ssum);
    }
}

原文地址:https://www.cnblogs.com/-guz/p/9787048.html

时间: 2024-08-30 18:24:30

【SP1043】GSS1 - Can you answer these queries I的相关文章

【BZOJ2482】[Spoj1557] Can you answer these queries II 线段树

[BZOJ2482][Spoj1557] Can you answer these queries II Description 给定n个元素的序列. 给出m个询问:求l[i]~r[i]的最大子段和(可选空子段). 这个最大子段和有点特殊:一个数字在一段中出现了两次只算一次. 比如:1,2,3,2,2,2出现了3次,但只算一次,于是这个序列的和是1+2+3=6. Input 第一行一个数n. 第二行n个数,为给定的序列,这些数的绝对值小于等于100000. 第三行一个数m. 接下来m行,每行两个

「SP1043」GSS1 - Can you answer these queries I

传送门 Luogu 解题思路 这题就是 GSS3 的一个退化版,不带修改操作的区间最大子段和,没什么好讲的. 细节注意事项 咕咕咕 参考代码 #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cctype> #include <cmath> #include &

SPOJ GSS1 Can you answer these queries I

Can you answer these queries I Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: GSS164-bit integer IO format: %lld      Java class name: Main You are given a sequence $A[1], A[2], ..., A[N] $. $( |A[i]| \leq

[SP1043]GSS1 - Can you answer these queries I

求区间内最大非空子段和,没什么可说的吧. 线段树,每个区间维护从左端开始的最大非空子段和,区间内的最大非空子段和,以右端结束的最大非空子段和,还有区间和. pushup()的写法要注意,不要漏掉任何一种情况. 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 inline int re

SP1043 GSS1 - Can you answer these queries I(线段树,区间最大子段和(静态))

题目描述 给出了序列A[1],A[2],…,A[N]. (a[i]≤15007,1≤N≤50000).查询定义如下: 查询(x,y)=max{a[i]+a[i+1]+...+a[j]:x≤i≤j≤y}. 给定M个查询,程序必须输出这些查询的结果. 输入输出格式 输入格式: 输入文件的第一行包含整数N. 在第二行,N个数字跟随. 第三行包含整数M. M行跟在后面,其中第1行包含两个数字xi和yi. 输出格式: 您的程序应该输出M查询的结果,每一行一个查询. 思路: 我们做这道题首先应该想的,是两个

SP1043 GSS1 - Can you answer these queries I(猫树)

给出了序列A[1],A[2],…,A[N]. (a[i]≤15007,1≤N≤50000).查询定义如下: 查询(x,y)=max{a[i]+a[i+1]+...+a[j]:x≤i≤j≤y}. 给定M个查询,程序必须输出这些查询的结果. 这就是一个最大子段和,用线段树就能直接搞掉 然后这里学习了一下一个叫做猫树的神奇东西->这里 能做到预处理之后查询$O(1)$ 1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 us

SP1043 GSS1 - Can you answer these queries I 线段树

问题描述 LG-SP1043 题解 GSS 系列第一题. \(q\) 个询问,求 \([x,y]\) 的最大字段和. 线段树,维护 \([x,y]\) 的 \(lmax,rmax,sum,val\) ,向上合并即可. 但是注意询问过程中也需要维护这些信息. \(\mathrm{Code}\) #include<bits/stdc++.h> using namespace std; template <typename Tp> void read(Tp &x){ x=0;ch

【html】学习记录-CSS的media queries属性

使用media queries属性可以根据浏览器的宽度自动选择激活需要的CSS定义:         其基本格式如下: @media screen and (min-width: 600px){ /* 即当屏幕宽度大于等于600px时触发此CSS定义 */ ... } @media screen and (max-width: 599px){ /* 即当屏幕宽度小于等于599px时触发此CSS定义 */ ... } 示例: <div class="container"> &

【sqli-labs】 less54 GET -Challenge -Union -10 queries allowed -Variation1 (GET型 挑战 联合查询 只允许10次查询 变化1)

尝试的次数只有10次 http://192.168.136.128/sqli-labs-master/Less-54/index.php?id=1' 单引号报错,错误信息没有显示 加注释符页面恢复正常,判断为单引号闭合 http://192.168.136.128/sqli-labs-master/Less-54/index.php?id=1'%23 通过页面信息可以判断查询的表至少有id,username,password三个字段,所以union select至少应该select3个字段 ht