好吧,我承认是sb题QAQ
BZOJ2171弱化版QAQ
这题考试的时候写的我快吐血了QAQ
0、题目大意:给一个序列,你可以随便修改,修改是将一个数+1或-1,一次修改的代价是1,问把这个数修改成x的交叉的上升序列或下降序列的最小代价
1、分析:是不是题目大意就看懵逼了,我们来解释一下,题目的意思就是让你把序列改成这样的
上升一波,下降一波,上升一波……或下降一波,上升一波,下降一波。。。
要求这个波动不能超过k-1
2、解题思路:分成4部分QAQ
a) k=1,直接输出中位数,mdzz.....
b) k=2,去点击题解最开始的链接,水题一道
c) k=3,这个就有一点意思了,我们求出1 -> i的上升的最小代价和下降的最小代价,n -> i的上升最小代价和下降的最小代价
然后这个数据只需要一个拐点,于是我们枚举端点,直接暴力求出答案。。。
d) k<=10,注意到这一波数据的n很小,那么我们可以预处理出l...r的上升和下降的最小代价
然后我们dp... f[i][j][k]表示第i为,已经搞了j波,现在要开始上升还是下降,然后做一个n^2k的sbdp
然后一个智障题就被我们AC了QAQ
#include <cmath> #include <cctype> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; #define LL int #define inf 1047483647 int a[100000]; namespace R { char Getc() { static const int LEN=1<<15; static char buf[LEN],*S=buf,*T=buf; if(S==T) { T=(S=buf)+fread(buf,1,LEN,stdin); if(S==T) return EOF; } return *S++; } int read() { static char ch; static int D; while(!isdigit(ch=Getc())); for(D=ch-'0';isdigit(ch=Getc());D=(D<<1)+(D<<3)+ch-'0'); return D; } } using namespace R; namespace merge_heap{ int ls[100000], rs[100000], value[100000], d[100000]; inline int merge(int x, int y){ if(!x) return y; if(!y) return x; if(value[x] > value[y]) swap(x, y); rs[x] = merge(rs[x], y); if(d[rs[x]] > d[ls[x]]) swap(ls[x], rs[x]); d[x] = d[ls[x]] + 1; return x; } inline int top(int x){ return value[x]; } inline int pop(int x){ return merge(ls[x], rs[x]); } inline void init(int x, int y){ ls[x] = rs[x] = 0; value[x] = y; d[x] = 1; } } namespace merge_heap1{ int ls[100000], rs[100000], value[100000], d[100000]; inline int merge(int x, int y){ if(!x) return y; if(!y) return x; if(value[x] < value[y]) swap(x, y); rs[x] = merge(rs[x], y); if(d[rs[x]] > d[ls[x]]) swap(ls[x], rs[x]); d[x] = d[ls[x]] + 1; return x; } inline int top(int x){ return value[x]; } inline int pop(int x){ return merge(ls[x], rs[x]); } inline void init(int x, int y){ ls[x] = rs[x] = 0; value[x] = y; d[x] = 1; } } int st[200010], tot; LL sum_mx[200010], sum_mn[200010], res[200010]; int size[200010]; int heap_size[200010]; LL xl[200010][2][2]; LL cost[1010][1010][2]; LL f[1010][20][2]; int n, k; inline void solve1(){ using namespace merge_heap; LL ans = 0; tot = 0; for(int i = 1; i <= n; i ++) init(i, a[i]); for(int i = 1; i <= n; i ++){ st[++ tot] = i; sum_mx[tot] = a[i]; heap_size[tot] = 1; res[tot] = 0; sum_mn[tot] = 0; size[tot] = 1; while(tot > 1 && top(st[tot]) > top(st[tot - 1])){ tot --; st[tot] = merge(st[tot + 1], st[tot]); sum_mx[tot] += sum_mx[tot + 1]; sum_mn[tot] += sum_mn[tot + 1]; heap_size[tot] += heap_size[tot + 1]; size[tot] += size[tot + 1]; res[tot] += res[tot + 1]; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]); ans += res[tot]; while(heap_size[tot] > size[tot] / 2 + 1){ sum_mn[tot] += top(st[tot]); sum_mx[tot] -= top(st[tot]); st[tot] = pop(st[tot]); heap_size[tot] --; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]); ans += res[tot]; } } xl[i][0][0] = ans; } ans = 0; tot = 0; for(int i = 1; i <= n / 2; i ++) swap(a[i], a[n - i + 1]); for(int i = 1; i <= n; i ++) init(i, a[i]); for(int i = 1; i <= n; i ++){ st[++ tot] = i; sum_mx[tot] = a[i]; heap_size[tot] = 1; res[tot] = 0; sum_mn[tot] = 0; size[tot] = 1; while(tot > 1 && top(st[tot]) > top(st[tot - 1])){ tot --; st[tot] = merge(st[tot + 1], st[tot]); sum_mx[tot] += sum_mx[tot + 1]; sum_mn[tot] += sum_mn[tot + 1]; heap_size[tot] += heap_size[tot + 1]; size[tot] += size[tot + 1]; res[tot] += res[tot + 1]; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]); ans += res[tot]; while(heap_size[tot] > size[tot] / 2 + 1){ sum_mn[tot] += top(st[tot]); sum_mx[tot] -= top(st[tot]); st[tot] = pop(st[tot]); heap_size[tot] --; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]); ans += res[tot]; } } xl[n - i + 1][1][0] = ans; } for(int i = 1; i <= n / 2; i ++) swap(a[i], a[n - i + 1]); } inline void solve2(){ using namespace merge_heap1; LL ans = 0; tot = 0; for(int i = 1; i <= n; i ++) init(i, a[i]); for(int i = 1; i <= n; i ++){ st[++ tot] = i; sum_mn[tot] = a[i]; heap_size[tot] = 1; res[tot] = 0; sum_mx[tot] = 0; size[tot] = 1; while(tot > 1 && top(st[tot]) < top(st[tot - 1])){ tot --; st[tot] = merge(st[tot + 1], st[tot]); sum_mx[tot] += sum_mx[tot + 1]; sum_mn[tot] += sum_mn[tot + 1]; res[tot] += res[tot + 1]; heap_size[tot] += heap_size[tot + 1]; size[tot] += size[tot + 1]; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]); ans += res[tot]; while(heap_size[tot] > size[tot] / 2 + 1){ sum_mx[tot] += top(st[tot]); sum_mn[tot] -= top(st[tot]); st[tot] = pop(st[tot]); heap_size[tot] --; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]); ans += res[tot]; } } xl[i][0][1] = ans; } ans = 0; tot = 0; for(int i = 1; i <= n / 2; i ++) swap(a[i], a[n - i + 1]); for(int i = 1; i <= n; i ++) init(i, a[i]); for(int i = 1; i <= n; i ++){ st[++ tot] = i; sum_mn[tot] = a[i]; heap_size[tot] = 1; res[tot] = 0; sum_mx[tot] = 0; size[tot] = 1; while(tot > 1 && top(st[tot]) < top(st[tot - 1])){ tot --; st[tot] = merge(st[tot + 1], st[tot]); sum_mx[tot] += sum_mx[tot + 1]; sum_mn[tot] += sum_mn[tot + 1]; heap_size[tot] += heap_size[tot + 1]; size[tot] += size[tot + 1]; res[tot] += res[tot + 1]; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]); ans += res[tot]; while(heap_size[tot] > size[tot] / 2 + 1){ sum_mx[tot] += top(st[tot]); sum_mn[tot] -= top(st[tot]); st[tot] = pop(st[tot]); heap_size[tot] --; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]); ans += res[tot]; } } xl[n - i + 1][1][1] = ans; } for(int i = 1; i <= n / 2; i ++) swap(a[i], a[n - i + 1]); } inline void solve3(int wt){ using namespace merge_heap1; LL ans = 0; tot = 0; for(int i = wt; i <= n; i ++) init(i, a[i]); for(int i = wt; i <= n; i ++){ st[++ tot] = i; sum_mn[tot] = a[i]; heap_size[tot] = 1; res[tot] = 0; sum_mx[tot] = 0; size[tot] = 1; while(tot > 1 && top(st[tot]) < top(st[tot - 1])){ tot --; st[tot] = merge(st[tot + 1], st[tot]); sum_mx[tot] += sum_mx[tot + 1]; sum_mn[tot] += sum_mn[tot + 1]; heap_size[tot] += heap_size[tot + 1]; size[tot] += size[tot + 1]; res[tot] += res[tot + 1]; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]); ans += res[tot]; while(heap_size[tot] > size[tot] / 2 + 1){ sum_mx[tot] += top(st[tot]); sum_mn[tot] -= top(st[tot]); st[tot] = pop(st[tot]); heap_size[tot] --; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(2 * heap_size[tot] - size[tot]) * top(st[tot]); ans += res[tot]; } } cost[wt][i][0] = ans; } } inline void solve4(int wt){ using namespace merge_heap; LL ans = 0; tot = 0; for(int i = wt; i <= n; i ++) init(i, a[i]); for(int i = wt; i <= n; i ++){ st[++ tot] = i; sum_mx[tot] = a[i]; heap_size[tot] = 1; res[tot] = 0; sum_mn[tot] = 0; size[tot] = 1; while(tot > 1 && top(st[tot]) > top(st[tot - 1])){ tot --; st[tot] = merge(st[tot + 1], st[tot]); sum_mx[tot] += sum_mx[tot + 1]; sum_mn[tot] += sum_mn[tot + 1]; heap_size[tot] += heap_size[tot + 1]; size[tot] += size[tot + 1]; res[tot] += res[tot + 1]; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]); ans += res[tot]; while(heap_size[tot] > size[tot] / 2 + 1){ sum_mn[tot] += top(st[tot]); sum_mx[tot] -= top(st[tot]); st[tot] = pop(st[tot]); heap_size[tot] --; ans -= res[tot]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]); ans += res[tot]; } } cost[wt][i][1] = ans; } } inline void inite(){ for(int wt = 1; wt <= n; wt ++){ solve3(wt); solve4(wt); } } //0 -> down //1 -> up int main(){ n = read(); k = read(); for(int i = 1; i <= n; i ++)a[i] = read(); if(k == 1){ sort(a + 1, a + n + 1); int o = a[n / 2 + 1]; LL ans = 0; for(int i = 1; i <= n; i ++) ans += abs(o - a[i]); printf("%d\n", ans); } else if(k == 2){ using namespace merge_heap; tot = 0; for(int i = 1; i <= n; i ++) init(i, a[i]); for(int i = 1; i <= n; i ++){ st[++ tot] = i; sum_mx[tot] = a[i]; heap_size[tot] = 1; res[tot] = 0; sum_mn[tot] = 0; size[tot] = 1; while(tot > 1 && top(st[tot]) > top(st[tot - 1])){ tot --; st[tot] = merge(st[tot + 1], st[tot]); sum_mx[tot] += sum_mx[tot + 1]; sum_mn[tot] += sum_mn[tot + 1]; heap_size[tot] += heap_size[tot + 1]; size[tot] += size[tot + 1]; res[tot] += res[tot + 1]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]); while(heap_size[tot] > size[tot] / 2 + 1){ sum_mn[tot] += top(st[tot]); sum_mx[tot] -= top(st[tot]); st[tot] = pop(st[tot]); heap_size[tot] --; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]); } } } LL ans = 0; for(int i = 1; i <= tot; i ++) ans += res[i]; tot = 0; for(int i = 1; i <= n / 2; i ++) swap(a[i], a[n - i + 1]); for(int i = 1; i <= n; i ++) init(i, a[i]); for(int i = 1; i <= n; i ++){ st[++ tot] = i; sum_mx[tot] = a[i]; heap_size[tot] = 1; res[tot] = 0; sum_mn[tot] = 0; size[tot] = 1; while(tot > 1 && top(st[tot]) > top(st[tot - 1])){ tot --; st[tot] = merge(st[tot + 1], st[tot]); sum_mx[tot] += sum_mx[tot + 1]; sum_mn[tot] += sum_mn[tot + 1]; heap_size[tot] += heap_size[tot + 1]; size[tot] += size[tot + 1]; res[tot] += res[tot + 1]; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]); while(heap_size[tot] > (size[tot] / 2 + 1)){ sum_mn[tot] += top(st[tot]); sum_mx[tot] -= top(st[tot]); st[tot] = pop(st[tot]); heap_size[tot] --; res[tot] = sum_mx[tot] - sum_mn[tot] + (LL)(size[tot] - 2 * heap_size[tot]) * top(st[tot]); } } } LL ans1 = 0; for(int i = 1; i <= tot; i ++) ans1 += res[i]; ans = min(ans, ans1); printf("%d\n", ans); } else if(k == 3){ LL ans = 1047483647; solve1(); solve2(); for(int i = 0; i <= n; i ++){ ans = min(ans, xl[i][0][0] + xl[i + 1][1][0]); ans = min(ans, xl[i][0][1] + xl[i + 1][1][1]); } printf("%d\n", ans); } else{ inite(); k --; for(int i = 0; i <= n; i ++){ for(int j = 0; j <= k; j ++){ for(int z = 0; z <= 1; z ++){ f[i][j][z] = inf; } } } f[0][0][0] = f[0][0][1] = 0; for(int i = 1; i <= n; i ++){ for(int j = 1; j <= k; j ++){ for(int z = 0; z <= 1; z ++){ for(int w = 0; w < i; w ++){ f[i][j][z] = min(f[i][j][z], f[w][j - 1][z ^ 1] + cost[w + 1][i][z ^ 1]); } } } } LL ans = inf; for(int i = 1; i <= k; i ++) ans = min(ans, min(f[n][i][0], f[n][i][1])); printf("%d\n", ans); } return 0; }