询问区间最大连续和,相同的只能算一次。可以不取,即为0

线段树在线做不到,只好离线搞。

一般最大连续和,都是以一个点为起点,往左或往右。其实,还可以以一个点为起点,往上最大是多少。

用pos标记一个数之前更新到的位置。

比如:-3 2 -3 1

用线段树成段覆盖:(越下方越早更新到)

1       1        1        1

       -3      -3

2      2

-3

nowsum表示当前深度积累的总和。

nowup表示当前深度从底往上的最大值。

totsum,totup同理,表示的是以某个叶子为起点对应的值。

加上读入优化,快了2s……

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<iostream>
  5 #define MAXN 200010
  6 #define S 100000
  7 typedef long long LL;
  8 using namespace std;
  9 struct seg {
 10     int left, right, id;
 11 };
 12 struct node {
 13     LL nowsum, nowup;
 14     LL totsum, totup;
 15 };
 16 seg p[MAXN];
 17 node tree[MAXN << 2];
 18 LL a[MAXN], ans[MAXN];
 19 int pos[MAXN];
 20 inline bool cmp(seg a, seg b) {
 21     return a.right < b.right;
 22 }
 23 inline LL MAX(LL x, LL y) {
 24     return x > y ? x : y;
 25 }
 26 void Build(int L, int R, int rt) {
 27     tree[rt].nowsum = tree[rt].nowup = 0;
 28     tree[rt].totsum = tree[rt].totup = 0;
 29     if (L != R) {
 30         int mid = (L + R) >> 1;
 31         Build(L, mid, rt << 1);
 32         Build(mid + 1, R, rt << 1 | 1);
 33     }
 34 }
 35 inline void PushUp(int rt) {
 36     tree[rt].totsum = MAX(tree[rt << 1].totsum, tree[rt << 1 | 1].totsum)
 37             + tree[rt].nowsum;
 38     tree[rt].totup = MAX(tree[rt << 1].totup, tree[rt << 1 | 1].totup);
 39     tree[rt].totup = MAX(tree[rt].totup,
 40             MAX(tree[rt << 1].totsum, tree[rt << 1 | 1].totsum)
 41                     + tree[rt].nowup);
 42 }
 43 inline void Down(int a, int b) {
 44     tree[b].nowup = MAX(tree[b].nowup, tree[b].nowsum + tree[a].nowup);
 45     tree[b].nowsum += tree[a].nowsum;
 46     PushUp(b);
 47 }
 48 inline void PushDown(int rt) {
 49     Down(rt, rt << 1);
 50     Down(rt, rt << 1 | 1);
 51     tree[rt].nowsum = tree[rt].nowup = 0;
 52 }
 53 void Update(int x, int y, int val, int L, int R, int rt) {
 54     if (x <= L && R <= y) {
 55         tree[rt].nowsum += val;
 56         tree[rt].nowup = MAX(tree[rt].nowup, tree[rt].nowsum);
 57         PushUp(rt);
 58     } else {
 59         int mid = (L + R) >> 1;
 60         PushDown(rt);
 61         if (x <= mid)
 62             Update(x, y, val, L, mid, rt << 1);
 63         if (y > mid)
 64             Update(x, y, val, mid + 1, R, rt << 1 | 1);
 65         PushUp(rt);
 66     }
 67 }
 68 LL Query(int x, int y, int L, int R, int rt) {
 69     if (x <= L && R <= y)
 70         return tree[rt].totup;
 71     else {
 72         int mid = (L + R) >> 1;
 73         LL res = 0;
 74         PushDown(rt);
 75         if (x <= mid)
 76             res = MAX(res, Query(x, y, L, mid, rt << 1));
 77         if (y > mid)
 78             res = MAX(res, Query(x, y, mid + 1, R, rt << 1 | 1));
 79         return res;
 80     }
 81 }
 82 int INT() {
 83     int res;
 84     char ch;
 85     bool neg;
 86     while (ch = getchar_unlocked(), !isdigit(ch) && ch != '-')
 87         ;
 88     if (ch == '-') {
 89         res = 0;
 90         neg = true;
 91     } else {
 92         res = ch - '0';
 93         neg = false;
 94     }
 95     while (ch = getchar_unlocked(), isdigit(ch))
 96         res = res * 10 + ch - '0';
 97     return neg ? -res : res;
 98 }
 99 int main() {
100     int n, i, j, q;
101     while (~scanf("%d", &n)) {
102         Build(1, n, 1);
103         memset(pos, 0, sizeof(pos));
104         for (i = 1; i <= n; i++)
105             a[i] = INT();
106         q = INT();
107         for (i = 0; i < q; i++) {
108             p[i].left = INT(), p[i].right = INT();
109             p[i].id = i;
110         }
111         sort(p, p + q, cmp);
112         for (i = 1, j = 0; i <= n && j < q; i++) {
113             Update(pos[a[i] + S] + 1, i, a[i], 1, n, 1);
114             pos[a[i] + S] = i;
115             for (; j < q && i == p[j].right; j++)
116                 ans[p[j].id] = Query(p[j].left, p[j].right, 1, n, 1);
117         }
118         for (i = 0; i < q; i++)
119             printf("%lld\n", ans[i]);
120     }
121     return 0;
122 }
posted on 2012-08-30 18:08  DrunBee  阅读(701)  评论(0编辑  收藏  举报