模拟。
遇到的坑是:1.题目中所指出的“硬盘数据大小 40KiB”指的是原始数据的大小,不是测试集中给出的16进制字符串的大小。
因为原始数据的长度是对应16进制表示的字符串长度的1/2(还应考虑空格的长度)。如果采用静态存储,应该为输入的字符串开辟更大的存储空间。
2.本题具有大量I/O,容易在I/O消耗大量时间,造成超时。
解决这个问题需要明确,当数据量巨大时,stdio与iostream两种I/O方式的效率存在明显差异,主要体现在如下两种情况:
1. ios::sync_with_stdio(true)(系统默认)
这种情况下运行时库会在内部同步iostream与stdio两种接口的状态。因此引入了由iostream向stdio同步的额外开销,这时stdio效率略高于iostream。
2. ios::sync_with_stdio(false)
手动关闭了上述同步。这时iostream与stdio状态独立,建议不要混合使用,但这就提高了iostream的效率。
iostream的cin/cout的数据类型是编译时确定的。相比之下scanf/printf还需要在运行时动态解析数据类型,引入额外的开销。
所以此时iostream效率高于stdio。
综上,使用"C++风格"的iostream,设置ios::sync_with_stdio(false)时,iostream效率高于stdio。
模拟RAID数据布局下的寻址的代码集中在Line 36~43,而冗余算法的实现紧接其后。分析发现,能够还原离线硬盘数据的条件是:阵列中现存硬盘数L应该仅比硬盘总数N小1,因此先判断能否还原,再按照冗余算法恢复数据即可。
AC的代码如下:
1 /* 2 * 1. stdio与iostream混合使用,iostream内部存在与stdio同步的开销,导致超时。 3 * 解决办法,统一使用iostream,设置ios::sync_with_stdio(false); 4 * 此时cin/cout快于scanf,printf。 5 * 2. 使用scanf, printf,耗时多于iostream(未关闭流同步)。 6 * 3. 题目中所指出的“硬盘数据大小 40KiB”指的是原始数据的大小,不是16进制字符串的大小!! 7 * 4. CSP似乎将可执行文件的加载时间也计算在总时间内。若在.bss开辟过大的数组,加载耗时过多,超时。 8 * “空间换时间”并不绝对可行。 9 */ 10 #include <iostream> 11 #include <cstdio> 12 #include <string> 13 #include <cstring> 14 15 #define N_DISK 1000+1 16 #define T_PER_BLK 8 17 18 using namespace std; 19 20 typedef unsigned int uint_t; 21 22 string ds[N_DISK]; 23 size_t ds_len; 24 string buff; 25 uint_t N, S, L; 26 27 inline uint_t toint(char h) { 28 return h>='0'&&h<='9'?h-'0':h-'A'+10; 29 } 30 31 inline char tohex(uint_t d) { 32 return d<=9?d+'0':d+'A'-10; 33 } 34 35 void read(uint_t block) { 36 uint_t stripe = block/S; 37 uint_t k = stripe / (N-1); 38 uint_t np = N-(k%N) -1; 39 uint_t offset = stripe - k * (N-1); 40 uint_t disk = (np+offset+1)%N; 41 42 uint_t blk = k*S + (block%S); 43 uint_t blk_offset = blk*T_PER_BLK; 44 45 buff = '-'; 46 47 if (blk_offset+T_PER_BLK <= ds_len) { 48 if (!ds[disk].empty()) { 49 cout << ds[disk].substr(blk_offset, T_PER_BLK) << endl; 50 return; 51 52 } else if (N-L == 1) { 53 buff = "00000000"; 54 for(uint_t i=0; i<N; i++) { 55 if (i==disk) continue; 56 57 for(uint_t j=0; j<T_PER_BLK; j++) { 58 buff[j] = tohex(toint(ds[i][blk_offset+j]) ^ toint(buff[j])); 59 } 60 } 61 } 62 } 63 64 cout << buff << endl; 65 } 66 67 int main(void) { 68 ios::sync_with_stdio(false); 69 cin >> N >> S >> L; 70 71 uint_t disk_id; 72 for(uint_t i=0; i<L; i++) { 73 cin >> disk_id; 74 cin >> ds[disk_id]; 75 } 76 ds_len = ds[disk_id].length(); 77 78 int M; 79 cin >> M; 80 for(int i=0; i<M; i++) { 81 uint_t block; 82 cin >> block; 83 84 read(block); 85 } 86 87 return 0; 88 }