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