Submission #114283

#TimeUsernameProblemLanguageResultExecution timeMemory
114283gs14004Space Pirate (JOI14_space_pirate)C++17
47 / 100
2064 ms48976 KiB
#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; } } 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 sgn = +1){ int ret = 0; if(dep[pos] < endDep && dep[pos] >= startDep) ret++; for(auto &i : tr[pos]){ if(!inCyc[i]){ ret += dfs3(i, startDep, endDep, sgn); } } if(dep[pos] == startDep) ans[0][pos] += ret * sgn; return ret; } int dfs4(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 += dfs4(i, startDep, endDep); } } 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 = i - cyc.size(); for(int j = 0; j < cyc.size(); j++){ int stDep = dep[cyc[j]] + d; stDep = max(stDep * 1ll, i - 1 - k % i); if(dep[cyc[j]] <= i - 1 - k % i){ dfs3(cyc[j], i - 1 - k % i, i - 1, +1); dfs3(cyc[j], i - 1 - k % i, stDep, -1); } else{ int fuck = dfs4(cyc[j], stDep, i - 1); ans[0][cyc[cyc.size() - i + k % i]] += fuck; } if(k % i < cyc.size()){ ans[0][cyc[k % i]] += dfs4(cyc[j], dep[cyc[j]] + d, stDep); } } } } } namespace Case2{ vector<int> tr[MAXN]; int num[MAXN], dep[MAXN]; void clear(){ for(int i=0; i<MAXN; i++){ num[i] = dep[i] = 0; tr[i].clear(); } } void add_edge(int s, int e){ tr[s].push_back(e); } void dfs(int x, vector<int> &v, lint k){ for(int i=num[x]; i<v.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 : tr[x]){ num[i] = num[x]; dep[i] = dep[x] + 1; dfs(i, v, k); } } void solve(vector<int> v, lint k){ for(int i=0; i<v.size(); i++){ num[v[i]] = i; dfs(v[i], v, k); } } } /// tree T /// query가 한 nlogn 개 정도 있는데 /// Q(i, j) <- depth = i인 노드들에 대해, /// 해당 노드의 subtree중 depth가 j 이하인 것들의 개수를 /// 다 그 노드에 대응되는 배열에 더해줌 vector<int> gph[MAXN]; int lvl[MAXN], dep[MAXN]; void dfs(int x){ for(auto &i : gph[x]){ lvl[i] = max(lvl[i], lvl[x]); dep[i] = dep[x] + 1; if(!cmp[i]) Case2::add_edge(x, i); dfs(i); } } void add_edge(int x){ for(auto &i : gph[x]){ if(cmp[i] == 2) continue; Case1::add_edge(x, i); Case2::add_edge(x, i); add_edge(i); } } void solve_cycle(vector<int> v, lint k){ for(auto &i : v){ add_edge(i); } Case1::solve(v, k); Case2::solve(v, k); Case2::clear(); } void solve_path(vector<int> v){ dfs(v.back()); Case2::solve(v, k); Case2::clear(); 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); } } 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); } } solve_cycle(cyc, k - pth.size()); if(pth.size()) solve_path(pth); 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:77:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for(int i=0; i+1<cyc.size(); i++){
                ~~~^~~~~~~~~~~
space_pirate.cpp:82:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for(int i = 2; i<=cyc.size(); i++){
                  ~^~~~~~~~~~~~
space_pirate.cpp:90:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    for(int j = 0; j < cyc.size(); j++){
                   ~~^~~~~~~~~~~~
space_pirate.cpp:101:14: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     if(k % i < cyc.size()){
        ~~~~~~^~~~~~~~~~~~
space_pirate.cpp: In function 'void Case2::dfs(int, std::vector<int>&, lint)':
space_pirate.cpp:122:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for(int i=num[x]; i<v.size(); i++){
                     ~^~~~~~~~~
space_pirate.cpp: In function 'void Case2::solve(std::vector<int>, lint)':
space_pirate.cpp:135:17: 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:192: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:194:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d",&a[i]);
   ~~~~~^~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...