This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
typedef long long lint;
typedef pair<int, int> pi;
const int mod = 1e9 + 7;
const int MAXN = 100005;
lint k;
int n, a[MAXN];
int par[60][MAXN];
lint ans[17][MAXN];
int cmp[MAXN];
lint anc(int x, lint k){
for(int i=0; k; i++){
if(k & 1){
x = par[i][x];
}
k >>= 1;
}
return x;
}
void add_path(int x, int c){
for(int i=0; c; i++){
if(c & 1){
ans[i][x]++;
x = par[i][x];
}
c >>= 1;
}
}
vector<int> gph[MAXN];
int lvl[MAXN], dep[MAXN];
int num[MAXN];
void dfs(int x){
for(auto &i : gph[x]){
lvl[i] = max(lvl[i], lvl[x]);
dep[i] = dep[x] + 1;
dfs(i);
}
}
namespace Case1{
vector<int> tr[MAXN];
int dep[MAXN];
bool inCyc[MAXN];
void add_edge(int s, int e){
tr[s].push_back(e);
}
void dfs(int x){
for(auto &i : tr[x]){
dep[i] = dep[x] + 1;
dfs(i);
}
}
int dfs2(int pos, int startDep, int endDep){
int ret = 0;
if(dep[pos] < endDep && dep[pos] >= startDep) ret++;
for(auto &i : tr[pos]) ret += dfs2(i, startDep, endDep);
if(dep[pos] == startDep) ans[0][pos] += ret;
return ret;
}
int dfs3(int pos, int startDep, int endDep){
int ret = 0;
if(dep[pos] < endDep && dep[pos] >= startDep) ret++;
for(auto &i : tr[pos]){
if(!inCyc[i]){
ret += dfs3(i, startDep, endDep);
}
}
if(dep[pos] == startDep) ans[0][pos] += ret;
return ret;
}
void solve(vector<int> cyc, lint k){
for(auto &i : cyc) inCyc[i] = 1;
for(int i=0; i+1<cyc.size(); i++){
tr[cyc[i+1]].push_back(cyc[i]);
}
dfs(cyc.back());
// beautiful case
for(int i = 2; i<=cyc.size(); i++){
int original_pinpoint = k % i;
dfs2(cyc.back(), i - k % i - 1, i - 1);
ans[0][cyc[original_pinpoint]] += dfs2(cyc.back(), -1, i - k % i - 1);
}
// ugly case
/*
for(int i = cyc.size() + 1; i <= n; i++){
int d = cyc.size() - i;
for(int j = 0; j < cyc.size(); j++){
int pos = max(i - 1 - k % i, 1ll * ((int)cyc.size() - 1 - j) + d);
dfs3(cyc[j], pos, i - 1 - k % i + j);
if(k % i < cyc.size()){
ans[0][cyc[k % i]] +=
dfs2(cyc[j], d, pos);
}
}
}*/
}
}
void dfsCyc(int x, vector<int> &cyc, lint k){
{
// TODO: quadratic
for(int i=0; i<num[x]; i++){
auto arrival = k;
int cycLength = dep[x] + cyc.size() - (num[x] - i) + 1;
if(cycLength <= cyc.size()) continue;
arrival %= cycLength;
if(arrival <= i){
ans[0][cyc[arrival]]++;
}
else{
arrival -= i + 1;
ans[0][anc(x, arrival)]++;
}
}
// TODO: quadratic
for(int i=num[x]; i<cyc.size(); i++){
auto arrival = k - i - 1;
int cycLength = dep[x] + i - num[x] + 1;
arrival %= cycLength;
ans[0][anc(x, arrival)]++;
}
}
for(auto &i : gph[x]){
if(cmp[i] == 2) continue;
Case1::add_edge(x, i);
num[i] = num[x];
dep[i] = dep[x] + 1;
dfsCyc(i, cyc, k);
}
}
void solve_cycle(vector<int> v, lint k){
for(int i=0; i<v.size(); i++){
num[v[i]] = i;
}
for(auto &i : v){
dfsCyc(i, v, k);
}
Case1::solve(v, k);
}
void solve_path(vector<int> v){ // TODO: quadratic
dep[v.back()] = 1;
dfs(v.back());
for(int i=1; i<=n; i++){
if(!cmp[par[20][i]]) continue;
int w = v.size() - lvl[i];
int pos = anc(i, k - w);
add_path(pos, w);
for(int j = 1; j <= lvl[i]; j++){
lint upV = k - (lvl[1] - j + 1);
upV %= (dep[i] - j + 1);
ans[0][anc(i, upV)]++;
}
}
}
int main(){
scanf("%d %lld",&n,&k);
for(int i=1; i<=n; i++){
scanf("%d",&a[i]);
gph[a[i]].push_back(i);
}
memcpy(par[0], a, sizeof(par[0]));
for(int i=1; i<60; i++){
for(int j=1; j<=n; j++){
par[i][j] = par[i-1][par[i-1][j]];
}
}
for(int i=1; cmp[i]<2; i=a[i]) cmp[i]++;
int pthcnt = n - count(cmp + 1, cmp + n + 1, 0);
int onecnt = count(cmp + 1, cmp + n + 1, 1);
ans[0][anc(1, k)] += 1ll * n * (n - pthcnt);
for(int i=1; i<=n; i++){
if(!cmp[par[20][i]]){
int pos = anc(i, k - pthcnt);
add_path(pos, pthcnt);
}
}
vector<int> pth;
vector<int> cyc;
for(int i=1; ; i=a[i]){
if(cmp[i] == 1){
lvl[i] = onecnt - pth.size();
pth.push_back(i);
}
if(cmp[i] == 2){
if(cyc.size() && i == cyc.front()) break;
cyc.push_back(i);
}
}
if(pth.size()) solve_path(pth);
solve_cycle(cyc, k - pth.size());
for(int i=16; i; i--){
for(int j=1; j<=n; j++){
ans[i - 1][par[i - 1][j]] += ans[i][j];
ans[i - 1][j] += ans[i][j];
}
}
for(int i=1; i<=n; i++) printf("%lld\n", ans[0][i]);
}
Compilation message (stderr)
space_pirate.cpp: In function 'void Case1::solve(std::vector<int>, lint)':
space_pirate.cpp:79:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for(int i=0; i+1<cyc.size(); i++){
~~~^~~~~~~~~~~
space_pirate.cpp:84:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for(int i = 2; i<=cyc.size(); i++){
~^~~~~~~~~~~~
space_pirate.cpp: In function 'void dfsCyc(int, std::vector<int>&, lint)':
space_pirate.cpp:111:17: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if(cycLength <= cyc.size()) continue;
~~~~~~~~~~^~~~~~~~~~~~~
space_pirate.cpp:122:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for(int i=num[x]; i<cyc.size(); i++){
~^~~~~~~~~~~
space_pirate.cpp: In function 'void solve_cycle(std::vector<int>, lint)':
space_pirate.cpp:140:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for(int i=0; i<v.size(); i++){
~^~~~~~~~~
space_pirate.cpp: In function 'int main()':
space_pirate.cpp:166:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
scanf("%d %lld",&n,&k);
~~~~~^~~~~~~~~~~~~~~~~
space_pirate.cpp:168:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
scanf("%d",&a[i]);
~~~~~^~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |