ZROI2017 做题笔记
基数排序,时间复杂度为 $O((n+d)\log_d{V})$,一般 $n\ge10^5$ 取 $d=2^{16}$ 很优秀,可以将 $\log_d{V}$ 看成是一个很小的常数。
注意序列存在负数时要先区分出正数和负数,分别进行基数排序。
1 const int N = 1e5 + 10; 2 int n, a[N]; 3 4 void radix_sort(unsigned int *a, int l, int r) 5 { 6 const unsigned int D = 1 << 16, k = D - 1; 7 static unsigned int b[N]; static int cnt[D]; 8 unsigned int *x = a, *y = b; 9 for (int i = 0; i < 32; i += 16) 10 { 11 for (int j = 0; j < D; ++j) cnt[j] = 0; 12 for (int j = l; j < r; ++j) ++cnt[x[j] >> i & k]; 13 for (int tot = 0, j = 0; j < D; ++j) tot += cnt[j], cnt[j] = tot - cnt[j]; 14 for (int j = l; j < r; ++j) y[++cnt[x[j] >> i & k]] = x[j]; 15 swap(x, y); 16 } 17 } 18 19 int main() 20 { 21 read(n); for (int i = 1; i <= n; ++i) read(a[i]); 22 radix_sort((unsigned int*)a, 1, n + 1); // 左闭右开 a[l,r) 23 for (int i = 1; i <= n; ++i) print(a[i]), pc(' '); 24 fwrite(pbuf, 1, pp - pbuf, stdout); return 0; 25 }
递归函数的写法应该是:
1 int f(int n) 2 { 3 if (n <= 2) return 1; 4 return f(n - 1) + f(n - 2); 5 }
改成非递归的手工栈需要储存函数参数、时间戳和答案,比较恶心但这也的确是 C++ 递归函数内部代码的形式。
1 const int N = 1e6 + 10; 2 int s[N][3]; 3 4 int f(int n) 5 { 6 int head = 1; s[1][0] = n, s[1][1] = s[1][2] = 0; 7 while (head) 8 { 9 if (!s[head][1]) 10 if (s[head][0] <= 2) s[head--][2] = 1; 11 else s[head][1] = 1, ++head, s[head][0] = s[head - 1][0] - 1, s[head][1] = s[head][2] = 0; 12 else if (s[head][1] & 1) 13 { 14 s[head][1] = 2, s[head][2] += s[head + 1][2]; 15 ++head, s[head][0] = s[head - 1][0] - 2, s[head][1] = s[head][2] = 0; 16 } 17 else s[head][2] += s[head + 1][2], --head; 18 } 19 return s[1][2]; 20 } 21 22 int main() 23 { 24 int t, n; read(t); while (t--) read(n), print(f(n)), pc('\n'); 25 fwrite(pbuf, 1, pp - pbuf, stdout); return 0; 26 }
HDU4699 Editor
然而 HDU 现在还没复活……virtual judge 上的题面 link。
To be continued...