题意:给定一个序列 s1, s2,...sn,以及一个k,求一个连续的k个数,把s[i]...s[i+k-1]变成一个数s',使得sigma(|s[j]-s'|)(i<=j<=i+k-1)最小
思路:最近无聊切起poi。。顿感智商不够。。
这道题很容易想到把这些数变成中位数最优。。那么就可以用平衡树维护了。。
当然,直接用set维护也就够了。。不过为了练练代码。。我还是写了下splay。。
code:
1 /* 2 * Author: Yzcstc 3 * Created Time: 2014/11/8 19:03:57 4 * File Name: klo.cpp 5 */ 6 #include<cstdio> 7 #include<iostream> 8 #include<cstring> 9 #include<cstdlib> 10 #include<cmath> 11 #include<algorithm> 12 #include<string> 13 #include<map> 14 #include<set> 15 #include<vector> 16 #include<queue> 17 #include<stack> 18 #include<ctime> 19 #define repf(i, a, b) for (int i = (a); i <= (b); ++i) 20 #define M0(x) memset(x, 0, sizeof(x)) 21 #define Inf 0x7fffffff 22 using namespace std; 23 const int maxn = 120000; 24 typedef long long ll; 25 int n, k; 26 int a[101010]; 27 #define L ch[x][0] 28 #define R ch[x][1] 29 #define KT ch[ch[root][0]][1] 30 struct SplayTree{ 31 int sz[maxn], pre[maxn], ch[maxn][2], v[maxn]; 32 ll sum[maxn]; 33 int m, root; 34 void push_up(const int& x){ 35 sz[x] = sz[L] + sz[R] + 1; 36 sum[x] = sum[L] + sum[R] + v[x]; 37 } 38 void init(){ 39 M0(sz), M0(pre), M0(ch), M0(ch), M0(v); 40 } 41 void push_down(const int& x){ 42 } 43 void rotate(int &x, const int f){ 44 int y = pre[x], z = pre[y]; 45 push_down(y), push_down(x); 46 ch[y][!f] = ch[x][f]; 47 pre[ch[x][f]] = y; 48 pre[x] = pre[y]; 49 if (z) ch[z][ch[z][1] == y] = x; 50 ch[x][f] = y; 51 pre[y] = x; 52 push_up(y); 53 } 54 void splay(int &x, const int g){ 55 push_down(x); 56 while (pre[x] != g){ 57 int y = pre[x], z = pre[y]; 58 if (z == g) rotate(x, ch[y][0] == x); 59 else { 60 int f = (ch[z][0] == y); 61 ch[y][!f] ? rotate(y, f) : rotate(x, !f); 62 rotate(x, f); 63 } 64 } 65 push_up(x); 66 if (!g) root = x; 67 } 68 void rto(int k,const int g, int& y){ 69 int x = root; 70 while (sz[L] + 1 != k){ 71 push_down(x); 72 if (sz[L] >= k) x = L; 73 else { 74 k -= sz[L] + 1; 75 x = R; 76 } 77 } 78 y = x; 79 splay(x, g); 80 } 81 int search(int x, int val){ 82 int y = -1; 83 while (x){ 84 y = x; 85 if (val <= v[x]) y = x, x = L; 86 else y = x, x = R; 87 } 88 return y; 89 } 90 void insert(int x, int val){ 91 int y = search(root, val); 92 ch[y][val > v[y]] = x; 93 pre[x] = y; 94 while (y) push_up(y), y = pre[y]; 95 splay(x, 0); 96 } 97 int findpre(int x){ 98 x = L; 99 while (R) x = R; 100 return x; 101 } 102 void split(int x){ 103 splay(x, 0); 104 int lt = findpre(x); 105 if (lt){ 106 splay(lt, x); 107 root = lt, pre[root] = 0; 108 ch[root][1] = R; 109 if (R) pre[R] = root; 110 } else root = R, pre[R] = 0; 111 push_up(root); 112 L = R = 0; 113 } 114 ll query(const int& n, int &vv){ 115 int k = (n+1) / 2, x; 116 if (!(n & 1)) ++k; 117 rto(k, 0, x); 118 ll res = (ll)v[x] * (k-1) - sum[ch[root][0]] + sum[ch[root][1]] - (ll)v[x] * (n-k); 119 vv = v[x]; 120 return res; 121 } 122 } S; 123 124 void init(){ 125 for (int i = 1; i <= n; ++i) 126 scanf("%d", &a[i]); 127 } 128 129 void solve(){ 130 if (k == 1){ 131 puts("0"); 132 for (int i = 1; i <= n; ++i) 133 printf("%d\n", a[i]); 134 return; 135 } 136 S.root = 1, S.sz[1] = 1, S.sum[1] = S.v[1] = a[1]; 137 for (int i = 2; i <= n; ++i) 138 S.sz[i] = 1, S.v[i] = S.sum[i] = a[i]; 139 for (int i = 2; i <= k; ++i) 140 S.insert(i, a[i]); 141 int ans_pos = 1, ans_val = 0, val; 142 ll ans = S.query(k, ans_val), tmp; 143 for (int i = k + 1; i <= n; ++i){ 144 S.split(i-k); 145 S.insert(i, a[i]); 146 tmp = S.query(k, val); 147 if (tmp < ans) 148 ans = tmp, ans_val = val, ans_pos = i - k + 1; 149 } 150 cout << ans << endl; 151 for (int i = ans_pos; i <= ans_pos+k-1; ++i) a[i] = ans_val; 152 for (int i = 1; i <= n; ++i) printf("%d\n", a[i]); 153 } 154 155 int main(){ 156 // freopen("a.in", "r", stdin); 157 // freopen("a.out", "w", stdout); 158 while (scanf("%d%d", &n, &k) != EOF){ 159 init(); 160 solve(); 161 } 162 return 0; 163 }