洛谷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 }
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 }