专题二树形结构 A - Can you answer these queries I

  1. 题目

    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.

    Example

    Input:
    3 
    -1 2 3
    1
    1 2
    
    Output:
    2
    
  2. 思路
    题目要求给一组数,查询某区间内最大连续和。对于一个节点代表的区间,以及它的左儿子右儿子,有如下情况以及关系:
    (sum:区间和;lsum:区间最大前缀和;rsum:区间最大后缀和;maxx:区间最大连续元素的和)

    此题甚至没有修改区间的操作,摸清规律写线段树就行了
  3. 代码
    这个实际上是C题代码,因为题目差别不大(C题只多了个修改),直接在A的基础上面改了,原来的找不到了,去掉change和输入的判断部分应该就是A的代码了
    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    #define clear(a,x) memset(a,x,sizeof(a))
    #define ll long long
    const int M=4e5;
    
    struct Node {
        int lsum, rsum, sum, maxx;
    }ss[M];
    
    int a[M << 2];//???
    //ll sum[M],lsum[M],rsum[M],maxx[M];
    int n,q;
    
    void up(int p)
    {
    	ss[p].sum = ss[p << 1].sum + ss[(p << 1) + 1].sum;
    	ss[p].lsum = max(ss[p << 1].lsum, ss[p << 1].sum + ss[p << 1 | 1].lsum);
    	ss[p].rsum = max(ss[p << 1 | 1].rsum, ss[p << 1 | 1].sum + ss[p << 1].rsum);
    	ss[p].maxx = max(max(ss[p << 1].maxx, ss[p << 1 | 1].maxx), ss[p << 1].rsum + ss[p << 1 | 1].lsum);
    }
    
    void build(int s, int t, int p) {
    
    	if (s == t) {
    	    ss[p].lsum = ss[p].rsum = ss[p].maxx = ss[p].sum = a[s];
    	    return;
    	}
    
    	int m = s + ((t - s) >> 1);
    	build(s, m, p << 1), build(m + 1, t, p << 1 | 1);
    	up(p);
    }
    
    void change(int x, int c, int s, int t, int p)
    {
    	int m = s + ((t - s) >> 1);
    	if (s == x && s == t) {
    		ss[p].maxx = ss[p].lsum = ss[p].rsum = ss[p].sum = c;
    		return;
    	}
    	if (x <= m) change(x, c, s, m, p << 1); else change(x, c, m+1, t, p << 1 | 1);
    	up(p);
    }
    
    Node query(int l, int r, int s, int t, int p){
        if (l <= s && t <= r) return ss[p];
        int m = s + ((t - s) >> 1);
        if (m >= r) return query(l, r, s, m, p << 1) ;
        else if (m < l) return query(l, r, m + 1, t, p << 1 | 1);
        else {
            Node ls = query(l, r, s, m, p << 1);
            Node rs = query(l, r, m + 1, t, p << 1 | 1);
            Node ans ;
            ans.maxx = max(max(ls.maxx, rs.maxx), ls.rsum + rs.lsum);
            ans.lsum = max(ls.lsum, ls.sum + rs.lsum);
            ans.rsum = max(rs.rsum, rs.sum + ls.rsum);
            ans.sum = ls.sum + rs.sum;
            return ans;
        }
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    	}
    	build(1,n,1);
    	scanf("%d",&q);
    	int op,x,y;
    	while (q--) {
    		cin >> op >> x >> y;
    		if(op==1)
    		{
    			cout << query(x, y, 1, n, 1).maxx <<endl;
    		}
    		else
    		{
    			change(x, y, 1, n, 1);
    		}
    	}
    	return 0;
    }
posted @ 2022-02-06 23:00  Benincasa  阅读(17)  评论(0编辑  收藏  举报