BZOJ2288 生日礼物
本题是数据备份的进阶版。
首先去掉所有0,把连续的正数/负数连起来。
计算所有正数段的个数与总和。
然后考虑数据备份,有一点区别:
如果我们在数列中选出一个负数,相当于把它左右连起来。
选出一个正数,相当于抛弃它。
总和加上那个负数/减去那个正数即为变化。
所以把val按照绝对值进堆,出来,减去绝对值即可。
注意:两边的负数不能选,因为旁边没有东西去给你连。
实际操作的时候我存了负数,在比较函数里加abs
1 #include <cstdio> 2 #include <queue> 3 #include <cmath> 4 const int N = 100010; 5 6 struct Sta { 7 int p, val; 8 Sta(int pq, int v) { 9 p = pq; 10 val = v; 11 } 12 }; 13 inline int abs(const int &x) { 14 return x > 0 ? x : -x; 15 } 16 inline bool operator <(const Sta &x, const Sta &y) { 17 return abs(x.val) > abs(y.val); 18 } 19 struct ListNode { 20 int pre, nex, val; 21 bool use; 22 }li[N << 1]; int top, head, tail; 23 24 int a[N], ans, cnt; 25 std::priority_queue<Sta> Q; 26 27 inline void init() { 28 head = (N << 1) - 1; 29 tail = head - 1; 30 li[head].nex = tail; 31 li[tail].pre = head; 32 return; 33 } 34 35 inline void add(int x) { 36 top++; 37 int p = li[tail].pre; 38 li[top].pre = p; 39 li[top].nex = tail; 40 li[p].nex = top; 41 li[tail].pre = top; 42 li[top].val = x; 43 Q.push(Sta(top, x)); 44 if(x > 0) { 45 ans += x; 46 cnt++; 47 } 48 return; 49 } 50 51 inline int get() { 52 Sta t = Q.top(); 53 Q.pop(); 54 while(!Q.empty() && (li[t.p].use || li[t.p].val != t.val)) { 55 t = Q.top(); 56 Q.pop(); 57 } 58 int x = t.p; 59 60 if(li[x].val < 0 && li[x].pre == head) { 61 li[x].use = 1; 62 li[li[x].nex].pre = head; 63 li[head].nex = li[x].nex; 64 return get(); 65 } 66 if(li[x].val < 0 && li[x].nex == tail) { 67 li[x].use = 1; 68 li[tail].pre = li[x].pre; 69 li[li[x].pre].nex = tail; 70 return get(); 71 } 72 73 if(li[x].nex == tail && li[x].pre == head) { 74 li[x].use = 1; 75 return li[x].val; 76 } 77 if(li[x].nex == tail) { 78 int ans = li[x].val; 79 li[x].val += li[li[x].pre].val; 80 li[li[x].pre].use = 1; 81 li[x].pre = li[li[x].pre].pre; 82 li[li[x].pre].nex = x; 83 Q.push(Sta(x, li[x].val)); 84 return ans; 85 } 86 if(li[x].pre == head) { 87 int ans = li[x].val; 88 li[x].val += li[li[x].nex].val; 89 li[li[x].nex].use = 1; 90 li[x].nex = li[li[x].nex].nex; 91 li[li[x].nex].pre = x; 92 Q.push(Sta(x, li[x].val)); 93 return ans; 94 } 95 int ans = li[x].val; 96 li[x].val += li[li[x].nex].val; 97 li[x].val += li[li[x].pre].val; 98 li[li[x].pre].use = 1; 99 li[li[x].nex].use = 1; 100 li[x].pre = li[li[x].pre].pre; 101 li[x].nex = li[li[x].nex].nex; 102 li[li[x].pre].nex = x; 103 li[li[x].nex].pre = x; 104 Q.push(Sta(x, li[x].val)); 105 return ans; 106 } 107 108 int main() { 109 int m, n; 110 init(); 111 scanf("%d%d", &n, &m); 112 for(int i = 1; i <= n; i++) { 113 scanf("%d", &a[i]); 114 } 115 int t = 0; 116 bool f = 1; 117 for(int i = 1; i <= n; i++) { 118 if(!a[i]) { 119 continue; 120 } 121 if(f) { 122 if(a[i] < 0) { 123 continue; 124 } 125 else { 126 f = 0; 127 } 128 } 129 if(1ll * a[i] * t >= 0) { 130 t += a[i]; 131 } 132 else { 133 add(t); 134 t = a[i]; 135 } 136 } 137 if(t > 0) { 138 add(t); 139 } 140 141 for(int i = m + 1; i <= cnt; i++) { 142 ans -= abs(get()); 143 } 144 printf("%d", ans); 145 return 0; 146 }