답안 #114283

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
114283 2019-05-31T17:00:54 Z gs14004 우주 해적 (JOI14_space_pirate) C++17
47 / 100
2000 ms 48976 KB
#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

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]);
   ~~~~~^~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 10 ms 8960 KB Output is correct
2 Correct 10 ms 8960 KB Output is correct
3 Correct 11 ms 8960 KB Output is correct
4 Correct 12 ms 8960 KB Output is correct
5 Correct 10 ms 8960 KB Output is correct
6 Correct 10 ms 8960 KB Output is correct
7 Correct 10 ms 8960 KB Output is correct
8 Correct 10 ms 8960 KB Output is correct
9 Correct 10 ms 8960 KB Output is correct
10 Correct 10 ms 8960 KB Output is correct
11 Correct 10 ms 8960 KB Output is correct
12 Correct 11 ms 8960 KB Output is correct
13 Correct 11 ms 8960 KB Output is correct
14 Correct 11 ms 8960 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 10 ms 8960 KB Output is correct
2 Correct 10 ms 8960 KB Output is correct
3 Correct 11 ms 8960 KB Output is correct
4 Correct 12 ms 8960 KB Output is correct
5 Correct 10 ms 8960 KB Output is correct
6 Correct 10 ms 8960 KB Output is correct
7 Correct 10 ms 8960 KB Output is correct
8 Correct 10 ms 8960 KB Output is correct
9 Correct 10 ms 8960 KB Output is correct
10 Correct 10 ms 8960 KB Output is correct
11 Correct 10 ms 8960 KB Output is correct
12 Correct 11 ms 8960 KB Output is correct
13 Correct 11 ms 8960 KB Output is correct
14 Correct 11 ms 8960 KB Output is correct
15 Correct 292 ms 10232 KB Output is correct
16 Correct 173 ms 10104 KB Output is correct
17 Correct 309 ms 10260 KB Output is correct
18 Correct 521 ms 10460 KB Output is correct
19 Correct 172 ms 10360 KB Output is correct
20 Correct 418 ms 10360 KB Output is correct
21 Correct 571 ms 10744 KB Output is correct
22 Correct 408 ms 10616 KB Output is correct
23 Correct 625 ms 10616 KB Output is correct
24 Correct 359 ms 10488 KB Output is correct
25 Correct 108 ms 10104 KB Output is correct
26 Correct 493 ms 10616 KB Output is correct
27 Correct 224 ms 10360 KB Output is correct
28 Correct 273 ms 10360 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1177 ms 48976 KB Output is correct
2 Execution timed out 2064 ms 46420 KB Time limit exceeded
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 10 ms 8960 KB Output is correct
2 Correct 10 ms 8960 KB Output is correct
3 Correct 11 ms 8960 KB Output is correct
4 Correct 12 ms 8960 KB Output is correct
5 Correct 10 ms 8960 KB Output is correct
6 Correct 10 ms 8960 KB Output is correct
7 Correct 10 ms 8960 KB Output is correct
8 Correct 10 ms 8960 KB Output is correct
9 Correct 10 ms 8960 KB Output is correct
10 Correct 10 ms 8960 KB Output is correct
11 Correct 10 ms 8960 KB Output is correct
12 Correct 11 ms 8960 KB Output is correct
13 Correct 11 ms 8960 KB Output is correct
14 Correct 11 ms 8960 KB Output is correct
15 Correct 292 ms 10232 KB Output is correct
16 Correct 173 ms 10104 KB Output is correct
17 Correct 309 ms 10260 KB Output is correct
18 Correct 521 ms 10460 KB Output is correct
19 Correct 172 ms 10360 KB Output is correct
20 Correct 418 ms 10360 KB Output is correct
21 Correct 571 ms 10744 KB Output is correct
22 Correct 408 ms 10616 KB Output is correct
23 Correct 625 ms 10616 KB Output is correct
24 Correct 359 ms 10488 KB Output is correct
25 Correct 108 ms 10104 KB Output is correct
26 Correct 493 ms 10616 KB Output is correct
27 Correct 224 ms 10360 KB Output is correct
28 Correct 273 ms 10360 KB Output is correct
29 Correct 1177 ms 48976 KB Output is correct
30 Execution timed out 2064 ms 46420 KB Time limit exceeded
31 Halted 0 ms 0 KB -