洛谷P3620 数据备份

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

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

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

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

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

这样递归下去即可。

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


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

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

堆优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代码
  1 #include <cstdio>
  2 #include <algorithm>
  3 using std::swap;
  4 typedef long long LL;
  5 const int N = 1000010;
  6 
  7 struct ListHeap {
  8     struct HeapNode {
  9         LL val;
 10         int p;
 11         bool operator < (const HeapNode &x) {
 12             return val < x.val;
 13         }
 14     }h[N];
 15     struct ListNode {
 16         LL val;
 17         int pre, nex, p;
 18     }li[N];
 19     int head, tail, top;
 20 
 21     ListHeap() {
 22         head = N - 1;
 23         tail = N - 2;
 24         top = 0;
 25         li[head].nex = tail;
 26         li[tail].pre = head;
 27     }
 28     inline void up(int x) {
 29         int s = x >> 1;
 30         while(x != 1 && h[x] < h[s]) {
 31             swap(h[x], h[s]);
 32             li[h[x].p].p = x;
 33             li[h[s].p].p = s;
 34             x = s;
 35             s = x << 1;
 36         }
 37         return;
 38     }
 39     inline void down(int x) {
 40         int s = x << 1;
 41         while(s <= top) {
 42             if(s < top && h[s | 1] < h[s]) {
 43                 s = s | 1;
 44             }
 45             if(h[s] < h[x]) {
 46                swap(h[x], h[s]);
 47                li[h[x].p].p = x;
 48                li[h[s].p].p = s;
 49                x = s;
 50                s = x << 1;
 51             }
 52             else break;
 53         }
 54         return;
 55     }
 56     inline void del(int x) {
 57         swap(h[x], h[top]);
 58         top--;
 59         li[h[x].p].p = x;
 60         up(x);
 61         down(x);
 62         return;
 63     }
 64     inline void insert(LL x) {
 65         int r = tail, l = li[tail].pre;
 66         int mid = ++top;
 67         li[mid].pre = l;
 68         li[mid].nex = r;
 69         li[l].nex = li[r].pre = mid;
 70         li[mid].val = x;
 71         li[mid].p = top;
 72         h[top].val = x;
 73         h[top].p = mid;
 74         up(top);
 75         return;
 76     }
 77     inline LL solve() {
 78         int mid = h[1].p;
 79         int l = li[mid].pre;
 80         int r = li[mid].nex;
 81         if(l == head && r == tail) {
 82             return h[1].val;
 83         }
 84         else if(l == head) {
 85             del(1);
 86             del(li[r].p);
 87             r = li[r].nex;
 88             li[l].nex = r;
 89             li[r].pre = l;
 90             return li[mid].val;
 91         }
 92         else if(r == tail) {
 93             del(1);
 94             del(li[l].p);
 95             l = li[l].pre;
 96             li[r].pre = l;
 97             li[l].nex = r;
 98             return li[mid].val;
 99         }
100         else {
101             del(li[l].p);
102             del(li[r].p);
103             LL ans = li[mid].val;
104             li[mid].val = li[l].val + li[r].val - ans;
105             l = li[l].pre;
106             r = li[r].nex;
107             li[l].nex = li[r].pre = mid;
108             li[mid].pre = l;
109             li[mid].nex = r;
110             h[li[mid].p].val = li[mid].val;
111             up(li[mid].p);
112             down(li[mid].p);
113             return ans;
114         }
115     }
116 }LH;
117 
118 int main() {
119     int n, k;
120     LL x, tx;
121     scanf("%d%d%lld", &n, &k, &tx);
122     for(int i = 2; i <= n; i++) {
123         scanf("%lld", &x);
124         LH.insert(x - tx);
125         tx = x;
126     }
127     LL ans = 0;
128     for(int i = 1; i <= k; i++) {
129         ans += LH.solve();
130     }
131     printf("%lld", ans);
132     return 0;
133 }
剧毒万紫千红结构体

 

posted @ 2018-05-26 17:21  garage  阅读(185)  评论(0编辑  收藏  举报