【SPOJ】1557 Can you answer these queries II

询问区间最大连续和,相同的只能算一次。可以不取,即为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 }

你可能感兴趣的:(poj)