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 }
AC代码

 

posted @ 2018-08-14 15:58  garage  阅读(311)  评论(0编辑  收藏  举报