uvalive 3938 "Ray, Pass me the dishes!" 线段树 区间合并

题意:求q次询问的静态区间连续最大和起始位置和终止位置 输出字典序最小的解.

思路:刘汝佳白书 每个节点维护三个值

pre, sub, suf 最大的前缀和, 连续和, 后缀和 然后这个题还要记录解的位置所以还要区间总和sum

  1 #include<iostream>
  2 #include<string>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<cstdio>
  6 #include<set>
  7 #include<map>
  8 #include<vector>
  9 #include<cstring>
 10 #include<stack>
 11 #include<cmath>
 12 #include<queue>
 13 #include <bits/stdc++.h>
 14 using namespace std;
 15 #define INF 0x3f3f3f3f
 16 #define ll long long
 17 #define clc(a,b) memset(a,b,sizeof(a))
 18 
 19 const int maxn = 500000 + 10;
 20 const int maxnode = 1000000 + 10;
 21 typedef long long LL;
 22 typedef pair<int,int> Interval;
 23 
 24 LL prefix_sum[maxn];
 25 
 26 LL sum(int L, int R)
 27 {
 28     return prefix_sum[R] - prefix_sum[L-1];
 29 }
 30 
 31 LL sum(Interval p)
 32 {
 33     return sum(p.first, p.second);
 34 }
 35 
 36 Interval better(Interval a, Interval b)
 37 {
 38     if(sum(a) != sum(b)) return sum(a) > sum(b) ? a : b;
 39     return a < b ? a : b; // 利用pair自带的字典序
 40 }
 41 
 42 int qL, qR;
 43 
 44 struct IntervalTree
 45 {
 46     int max_prefix[maxnode];
 47     int max_suffix[maxnode];
 48     Interval max_sub[maxnode];
 49 
 50     void build(int o, int L, int R)
 51     {
 52         if(L == R)
 53         {
 54             max_prefix[o] = max_suffix[o] = L;
 55             max_sub[o] = make_pair(L, L);
 56         }
 57         else
 58         {
 59             int M = L + (R-L)/2;
 60             // 递归创建子树
 61             int lc = o*2, rc = o*2+1;
 62             build(lc, L, M);
 63             build(rc, M+1, R);
 64 
 65             // 递推max_prefix
 66             LL v1 = sum(L, max_prefix[lc]);
 67             LL v2 = sum(L, max_prefix[rc]);
 68             if(v1 == v2) max_prefix[o] = min(max_prefix[lc], max_prefix[rc]);
 69             else max_prefix[o] = v1 > v2 ? max_prefix[lc] : max_prefix[rc];
 70 
 71             // 递推max_suffix
 72             v1 = sum(max_suffix[lc], R);
 73             v2 = sum(max_suffix[rc], R);
 74             if(v1 == v2) max_suffix[o] = min(max_suffix[lc], max_suffix[rc]);
 75             else max_suffix[o] = v1 > v2 ? max_suffix[lc] : max_suffix[rc];
 76 
 77             // 递推max_sub
 78             max_sub[o] = better(max_sub[lc], max_sub[rc]); // 完全在左子树或者右子树
 79             max_sub[o] = better(max_sub[o], make_pair(max_suffix[lc], max_prefix[rc])); // 跨越中线
 80         }
 81     }
 82 
 83     Interval query_prefix(int o, int L, int R)
 84     {
 85         if(max_prefix[o] <= qR) return make_pair(L, max_prefix[o]);
 86         int M = L + (R-L)/2;
 87         int lc = o*2, rc = o*2+1;
 88         if(qR <= M) return query_prefix(lc, L, M);
 89         Interval i = query_prefix(rc, M+1, R);
 90         i.first = L;
 91         return better(i, make_pair(L, max_prefix[lc]));
 92     }
 93 
 94     Interval query_suffix(int o, int L, int R)
 95     {
 96         if(max_suffix[o] >= qL) return make_pair(max_suffix[o], R);
 97         int M = L + (R-L)/2;
 98         int lc = o*2, rc = o*2+1;
 99         if(qL > M) return query_suffix(rc, M+1, R);
100         Interval i = query_suffix(lc, L, M);
101         i.second = R;
102         return better(i, make_pair(max_suffix[rc], R));
103     }
104 
105     Interval query(int o, int L, int R)
106     {
107         if(qL <= L && R <= qR) return max_sub[o];
108         int M = L + (R-L)/2;
109         int lc = o*2, rc = o*2+1;
110         if(qR <= M) return query(lc, L, M);
111         if(qL > M) return query(rc, M+1, R);
112         Interval i1 = query_prefix(rc, M+1, R); // 右半的前缀
113         Interval i2 = query_suffix(lc, L, M); // 左半的后缀
114         Interval i3 = better(query(lc, L, M), query(rc, M+1, R));
115         return better(make_pair(i2.first, i1.second), i3);
116     }
117 };
118 
119 IntervalTree tree;
120 
121 int main()
122 {
123     int kase = 0, n, a, Q;
124     while(scanf("%d%d", &n, &Q) == 2)
125     {
126         prefix_sum[0] = 0;
127         for(int i = 0; i < n; i++)
128         {
129             scanf("%d", &a);
130             prefix_sum[i+1] = prefix_sum[i] + a;
131         }
132         tree.build(1, 1, n);
133         printf("Case %d:\n", ++kase);
134         while(Q--)
135         {
136             int L, R;
137             scanf("%d%d", &L, &R);
138             qL = L;
139             qR = R;
140             Interval ans = tree.query(1, 1, n);
141             printf("%d %d\n", ans.first, ans.second);
142         }
143     }
144     return 0;
145 }
View Code

 

你可能感兴趣的:(uvalive 3938 "Ray, Pass me the dishes!" 线段树 区间合并)