| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
O(n) 解法,关键在于判环与映射。Key 是单射,所以规则对应了若干个环(如 key 为 {3, 2, 1} 时候(1-base),对于下标 1 的元素来说,第 1 次移动到下标 3,第 2 次移动到下标 1,故这个环长度为 2;相对地,下标 2 的元素所在的环是一个长度为 1 的自环)。找出这些环,并规定好原下标对应的位置(映射),即可在生成答案串时,对于某一 idx ,通过 (映射位置 + 环长) % k 得到最终位置,具体操作可参考如下代码:
```core code (cpp)
struct rule {
rule(int size) : size(size), id(size), offset(size) {}
std::vector<std::vector<int> > loops;
std::vector<int> id; // id[i]: the i-th elem is in id[i]-th loop
std::vector<int> offset; // offset[i]: the i-th elem is at offset[i] in loop
int size;
};
rule get_rule(std::vector<int>& key) {
const int N = key.size();
std::vector<bool> vis(N);
rule res(N);
for (int i = 0; i < N; i++) {
if (vis[i]) continue;
std::vector<int> loop;
for (int p = i; !vis[p]; p = key[p]) {
vis[p] = true;
loop.push_back(p);
}
for (int j = 0; j < loop.size(); j++) {
res.id[loop[j]] = res.loops.size();
res.offset[loop[j]] = j;
}
// res.loops.emplace_back(loop);
res.loops.push_back(loop);
}
return res;
}
std::string encode(const rule& R, int k, std::string& s) {
while (s.length() < R.size) s += ' ';
std::string res(R.size, ' ');
for (int i = 0; i < R.size; i++) {
const std::vector<int>& loop = R.loops[R.id[i]];
res[loop[(R.offset[i] + k) % loop.size()]] = s[i];
}
return res;
}
void solve(const rule& R) {
int k;
std::string s;
while (true) {
std::cin >> k;
if (k == 0) return;
std::cin.get();
std::getline(std::cin, s);
std::cout << encode(R, k, s) << "\n";
}
}
int main() {
for (int n; ; ) {
std::cin >> n;
if (n == 0) break;
std::vector<int> key(n);
for (int i = 0; i < n; i++) {
std::cin >> key[i];
key[i]--;
}
rule r = get_rule(key);
solve(r);
std::cout << "\n";
}
return 0;
}
```
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator