Can you answer these queries I (线段树)

来源:互联网 发布:福州锐掌网络怎么样 编辑:程序博客网 时间:2024/06/07 01:37
You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 ). A query is defined as follows:Query(x,y) = Max { a[i]+a[i+1]+...+a[j] ; x ≤ i ≤ j ≤ y }.Given M queries, your program must output the results of these queries.Input    The first line of the input file contains the integer N.    In the second line, N numbers follow.    The third line contains the integer M.    M lines follow, where line i contains 2 numbers xi and yi.Output    Your program should output the results of the M queries, one query per line. ExampleInput:3 -1 2 311 2Output:2

这个题就是给你一个区间 然后再这个区间里面找出一个最大的子区间和

#include<iostream>#include<string.h>#include<algorithm>#include<stdio.h>#define MAXN 50007 *4using namespace std;struct Node{    long left,right;    long long lsum,rsum,sum,ans;//lsum代表左端点的最大连续和     //rsum 代表以右结尾的最大连续和     //sum 代表区间和 ans 代表最后的结果}tree[MAXN];void createTree(long rt,long l,long r){    tree[rt].left = l;    tree[rt].right = r;    if(l==r)//到达叶子节点    {        scanf("%lld",&tree[rt].ans);        tree[rt].lsum = tree[rt].rsum = tree[rt].sum = tree[rt].ans;        return;    }    //递归创建左子树    long mid = (l+ r)/2;    createTree(rt*2,l,mid);    createTree(rt*2+1,mid+1,r);    /*    利用回溯来更新父节点的信息;    */    //左端点的连续最大值有两种情况 一种就是左子树的lsum    tree[rt].lsum = tree[rt*2].lsum;    //另外一种情况就是左子树的全部sum + 右子树的lsum    tree[rt].lsum = max(tree[rt].lsum,tree[rt*2].sum + tree[rt*2+1].lsum);    //同理可求右子树    tree[rt].rsum = tree[rt*2+1].rsum;    tree[rt].rsum = max(tree[rt].rsum,tree[rt*2+1].sum + tree[rt*2].rsum);    //区间和    tree[rt].sum = tree[rt*2].sum + tree[rt*2+1].sum;    //结果也是有两种情况的 第一种是取左右子树的某一个最大值 另外一种就是    //最大连续的区间两个子树都有 即 左子树的 rsum + 右子树的 lsum 这种情况也可能会出现最大值    tree[rt].ans = max(tree[rt*2].ans,tree[rt*2+1].ans);    tree[rt].ans = max(tree[rt].ans,tree[rt*2].rsum + tree[rt*2+1].lsum);}Node query(long rt,long l,long r)//rt代表根节点 l,r 代表区间的范围{    if(tree[rt].left == l && tree[rt].right == r)//到达叶子节点    {        return tree[rt];    }    long mid = ( tree[rt].left + tree[rt].right )/2;    if(r <= mid )    {      return  query(rt*2,l,r);//待查询的区间位于左子树 那么就直接查询左子树    }    else if(l>mid)//如果l大于mid 那么就是在右子树因为右子树的范围就是mid+1,r    {        return query(rt*2+1,l,r);    }    else    {        Node res;        Node lres,rres;        //如果不满足以上的情况 那么就是说明了所查区间就是tree[rt]的一个子集        lres = query(rt*2,l,mid);        rres = query(rt*2+1,mid+1,r);        res.sum = lres.sum + rres.sum;        res.lsum = max(lres.lsum,lres.sum + rres.lsum);        res.rsum = max(rres.rsum,rres.sum + lres.rsum);        res.ans = max(lres.rsum + rres.lsum,max(lres.ans,rres.ans));        return res;    }}int main(){    int n,m;    scanf("%d",&n);    createTree(1,1,n);    scanf("%d",&m);    while(m--)    {        int l,r;        scanf("%d%d",&l,&r);        Node res = query(1,l,r);        printf("%lld\n",res.ans);    }    return 0;}
阅读全文
0 0
原创粉丝点击