好吧,我一开始说这是个神级数据结构毒瘤题,后来改成神题了。

主要是贪心做法的巧妙转化:

首先发现选择的一对必须相邻,于是我们搞出差分。

然后考虑选取最小值时,最小值两侧的数要么同时选,要么都不选。

然后考虑把这三个数合起来变成sum[l] + sum[r] - sum[mid]

这样递归下去即可。

仔细思考,实在是巧妙至极啊!!!


关于代码实现:书上说要在堆和链表上建立映射关系,我觉得十分的毒瘤,打了135行结果五彩斑斓......

洛谷P3620 数据备份

 然后我决定放弃,不调了,采用神奇的:延迟删除法!就是取堆顶的时候判断。

堆优dijkstra就是这样做的。然后就A了....A了??!!Ahhh

实在是...惨不忍睹。

我TM之前在干嘛。

  1 #include <cstdio>
  2 #include <queue>
  3 typedef long long LL;
  4 const int N = 100010;
  5 
  6 struct HeapNode {
  7     LL val;
  8     int p;
  9     bool operator < (const HeapNode &x) const {
 10         return val > x.val;
 11     }
 12 };
 13 
 14 std::priority_queue<HeapNode> Q;
 15 
 16 struct ListNode {
 17     LL val;
 18     int pre, nex;
 19     bool del;
 20 }li[N]; int head, tail, top;
 21 
 22 void ListInit() {
 23     head = N - 1;
 24     tail = N - 2;
 25     li[head].nex = tail;
 26     li[tail].pre = head;
 27     return;
 28 }
 29 
 30 void insert(LL x) {
 31     HeapNode hd;
 32     hd.val = x;
 33     hd.p = ++top;
 34     Q.push(hd);
 35     int r = tail;
 36     int l = li[r].pre;
 37     li[top].val = x;
 38     li[l].nex = li[r].pre = top;
 39     li[top].pre = l;
 40     li[top].nex = r;
 41     return;
 42 }
 43 
 44 LL solve() {
 45     HeapNode hd = Q.top();
 46     Q.pop();
 47     int pos = hd.p;
 48     while(li[pos].del || li[pos].val != hd.val) {
 49         hd = Q.top();
 50         Q.pop();
 51         pos = hd.p;
 52     }
 53     int l = li[pos].pre;
 54     int r = li[pos].nex;
 55     int l2 = li[l].pre;
 56     int r2 = li[r].nex;
 57     LL ans = hd.val;
 58     if(l == head && r == tail) {
 59         ;
 60     }
 61     else if(l == head) {/// l pos r r2
 62         li[pos].del = li[r].del = 1;
 63         li[l].nex = r2;
 64         li[r2].pre = l;
 65     }
 66     else if(r == tail) {/// l2 l pos r
 67         li[pos].del = li[l].del = 1;
 68         li[r].pre = l2;
 69         li[l2].nex = r;
 70     }
 71     else{               /// l2 l pos r r2
 72         li[l].del = li[r].del = 1;
 73         li[pos].val = li[l].val + li[r].val - ans;
 74         li[l2].nex = li[r2].pre = pos;
 75         li[pos].pre = l2;
 76         li[pos].nex = r2;
 77         hd.val = li[pos].val;
 78         Q.push(hd);
 79     }
 80     return ans;
 81 }
 82 
 83 int main() {
 84     int k, n;
 85     LL x, tx;
 86     scanf("%d%d", &n, &k);
 87     scanf("%lld", &tx);
 88     for(int i = 2; i <= n; i++) {
 89         scanf("%lld", &x);
 90         insert(x - tx);
 91         tx = x;
 92     }
 93     LL ans = 0;
 94     for(int i = 1; i <= k; i++) {
 95         LL temp = solve();
 96         //printf("%lld \n", temp);
 97         ans += temp;
 98     }
 99     printf("%lld", ans);
100     return 0;
101 }
AC代码

相关文章:

  • 2021-12-02
  • 2021-06-15
  • 2021-06-02
  • 2021-12-30
猜你喜欢
  • 2021-10-02
  • 2022-01-03
  • 2021-11-23
  • 2021-06-27
  • 2021-08-29
  • 2021-06-14
  • 2021-11-06
相关资源
相似解决方案