CSP 201903-3 损坏的RAID5

真是没想到这道题还能被IO卡住。原本的做法是scanf”%8X”读,然后用getchar试探换行符。结果T。再试把试探删了,始终不行。最后放弃直接读Binary的想法,用的时候再做转换,直接读字符串进来。总算过了。

希望明天别遇上这么恶心的IO。今天晚上整理一下cstdio和iostream的格式化相关文档,明天考CSP使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <string>
#include <deque>
#include <algorithm>
#include <tuple>
using namespace std;

int n, s, l;
vector<string> RAIDArray;
int diskBlockCount;
char buf[100];

void input(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>n>>s>>l;
    RAIDArray.resize(n);
    for(int i=0;i<l;i++){
        int diskID, data;
        int bCnt = 0;
        string s;
        cin>>diskID>>s;
        RAIDArray[diskID]=s;
        diskBlockCount = s.size() / 8;
    }
}

int RAID(int diskID, int localBlockID){
    int data;
    sscanf((char *)&RAIDArray[diskID].c_str()[localBlockID*8],"%8X",&data);
    return data;
}

inline bool isDiskExists(int diskID){
    return !RAIDArray[diskID].empty();
}

inline int getGlobalStripeID(int blockID){
    return blockID / s;
}

inline int getLocalStripeID(int globalStripeID){
    return globalStripeID / (n-1);
}

inline int getlocalStripeECCDiskID(int localStripeID){
    return n - 1 - localStripeID % n;
}

inline std::tuple<int, int> getLocalDiskAndBlockID(int blockID){
    // Return Disk ID, Local Block ID
    int globalStripeID = getGlobalStripeID(blockID);
    int localStripeID = getLocalStripeID(globalStripeID);
    int localStripeECCDiskID = getlocalStripeECCDiskID(localStripeID);
    int localStripeDiskID = (localStripeECCDiskID + 1 + globalStripeID % (n-1)) % n;
    int localBlockID = localStripeID * s + blockID % s;
    return std::tuple<int, int>(localStripeDiskID, localBlockID);
}

inline std::tuple<bool, int> recoverDataDirect(int blockID){
    int diskID, localBlockID;
    std::tie(diskID, localBlockID) = getLocalDiskAndBlockID(blockID);
    if(!isDiskExists(diskID))
        return std::tuple<bool, int>(false, -1);
    else
        return std::tuple<bool, int>(true, RAID(diskID, localBlockID));
}

inline std::tuple<bool, int> recoverDataECC(int blockID){
    if(l < n-1)
        return std::tuple<bool, int>(false, -1);
    int diskID, localBlockID;
    int data = 0;
    std::tie(diskID, localBlockID) = getLocalDiskAndBlockID(blockID);
    for(int curDisk = 0;curDisk<n;curDisk++){
        if(curDisk == diskID)continue;
        data ^= RAID(curDisk,localBlockID);
    }
    return std::tuple<bool, int>(true, data);
}

inline std::tuple<bool, int> recoverDataMain(int blockID){
    int diskID, localBlockID;
    std::tie(diskID, localBlockID) = getLocalDiskAndBlockID(blockID);
    if(localBlockID >= diskBlockCount)
        return std::tuple<bool, int> (false, -1);
    bool flag;
    int result;
    std::tie(flag, result) = recoverDataDirect(blockID);
    if(flag)
        return std::tuple<bool, int> (flag, result);
    std::tie(flag, result) = recoverDataECC(blockID);
    if(flag)
        return std::tuple<bool, int> (flag, result);
    return std::tuple<bool, int> (false, -1);
}

void solve(){
    int m, blockID;
    cin>>m;
    while(m--){
        cin>>blockID;
        bool flag;
        int result;
        tie(flag, result) = recoverDataMain(blockID);
        if(!flag)
            cout<<"-\n";
        else
            cout<<setw(8)<<setfill('0')<<hex<<uppercase<<result<<"\n";
    }
}

int main(){
    input();
    solve();
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注