結果

問題 No.363 門松サイクル
ユーザー FF256grhyFF256grhy
提出日時 2016-04-19 15:24:25
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 172 ms / 4,000 ms
コード長 3,074 bytes
コンパイル時間 223 ms
コンパイル使用メモリ 26,236 KB
実行使用メモリ 20,308 KB
最終ジャッジ日時 2024-04-15 03:44:34
合計ジャッジ時間 3,712 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
7,536 KB
testcase_01 AC 2 ms
7,544 KB
testcase_02 AC 3 ms
9,588 KB
testcase_03 AC 3 ms
7,552 KB
testcase_04 AC 3 ms
7,540 KB
testcase_05 AC 3 ms
7,544 KB
testcase_06 AC 3 ms
7,612 KB
testcase_07 AC 3 ms
7,548 KB
testcase_08 AC 3 ms
7,676 KB
testcase_09 AC 54 ms
17,176 KB
testcase_10 AC 50 ms
15,024 KB
testcase_11 AC 130 ms
19,808 KB
testcase_12 AC 124 ms
19,948 KB
testcase_13 AC 102 ms
19,956 KB
testcase_14 AC 82 ms
19,696 KB
testcase_15 AC 118 ms
19,476 KB
testcase_16 AC 93 ms
17,280 KB
testcase_17 AC 172 ms
20,100 KB
testcase_18 AC 116 ms
20,008 KB
testcase_19 AC 82 ms
20,308 KB
testcase_20 AC 111 ms
20,164 KB
testcase_21 AC 170 ms
20,016 KB
testcase_22 AC 115 ms
19,868 KB
testcase_23 AC 132 ms
18,356 KB
testcase_24 AC 2 ms
7,672 KB
testcase_25 AC 2 ms
7,536 KB
testcase_26 AC 152 ms
20,252 KB
testcase_27 AC 148 ms
20,248 KB
testcase_28 AC 141 ms
20,132 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.cpp: In function ‘int main()’:
main.cpp:63:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   63 |         scanf("%d", &n);
      |         ~~~~~^~~~~~~~~~
main.cpp:64:39: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   64 |         for(i = 0; i < n; i++) { scanf("%d", &a[i]); }
      |                                  ~~~~~^~~~~~~~~~~~~
main.cpp:65:43: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   65 |         for(i = 0; i < n - 1; i++) { scanf("%d%d", &x[i], &y[i]); x[i]--; y[i]--; }
      |                                      ~~~~~^~~~~~~~~~~~~~~~~~~~~~
main.cpp:66:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   66 |         scanf("%d", &q);
      |         ~~~~~^~~~~~~~~~
main.cpp:67:43: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   67 |         for(i = 0; i < q    ; i++) { scanf("%d%d", &u[i], &v[i]); u[i]--; v[i]--; }
      |                                      ~~~~~^~~~~~~~~~~~~~~~~~~~~~

ソースコード

diff #

#include <stdio.h>

int isK(int a, int b, int c) {
	return ( (a < b && b > c && a != c) || (a > b && b < c && a != c) );
}

#define MAX 100000
#define NIL  0
#define ROOT 0

int n, a[MAX], x[MAX], y[MAX], q, u[MAX], v[MAX];
int first[MAX], last[MAX], list_val[MAX * 2 + 1], list_next[MAX * 2 + 1], ptr = 1;
int queue_val[MAX], get, set;
int height[MAX], ancestor[MAX][17], is_kado[MAX][17], flag[MAX];
// ancestor は 2^n 上のノード, is_kado は 2^n + 1 までが門松列かどうか

void add(int xx, int yy) {
	if(first[xx] == NIL) {
		first[xx] = ptr;
	} else {
		list_next[ last[xx] ] = ptr;
	}
	last[xx] = ptr;
	list_val[ptr] = yy;
	list_next[ptr] = NIL;
	ptr++;
}

int up(int s, int n) {
	int i = 0;
	while(n) {
		if(n % 2) { s = ancestor[s][i]; }
		n /= 2;
		i++;
	}
	return s;
}

int len(int n) {
	int i = 0;
	while(n) {
		n /= 2;
		i++;
	}
	return i;
}

int is_kado_func(int s, int t) {
	// s から tの次 まで
	int n = height[s] - height[t];
	int i, ans = 1;
	for(i = 0; i < len(n); i++) {
		if(n & (1 << i)) {
			ans &= is_kado[s][i];
			s = ancestor[s][i];
		}
	}
	return ans;
}

int main() {
	int i, j;
	scanf("%d", &n);
	for(i = 0; i < n; i++) { scanf("%d", &a[i]); }
	for(i = 0; i < n - 1; i++) { scanf("%d%d", &x[i], &y[i]); x[i]--; y[i]--; }
	scanf("%d", &q);
	for(i = 0; i < q    ; i++) { scanf("%d%d", &u[i], &v[i]); u[i]--; v[i]--; }
	
	for(i = 0; i < n - 1; i++) {
		add(x[i], y[i]);
		add(y[i], x[i]);
	}
	
	queue_val[set] = ROOT; set++;
	flag[ROOT] = 1;
	height[ROOT] = 0;
	while(get != set) {
		int qv = queue_val[get];
		int p = first[qv];
		while(p != NIL) {
			int lv = list_val[p];
			if(! flag[lv]) {
				flag[lv] = 1;
				queue_val[set] = lv; set++;
				height[lv] = height[qv] + 1;
				ancestor[lv][0] = qv;
				for(i = 0; i < len(height[lv]) - 1; i++) {
					ancestor[lv][i + 1] = ancestor[ ancestor[lv][i] ][i];
				}		
				if(height[lv] >= 2) {
					is_kado[lv][0] = isK( a[lv], a[ ancestor[lv][0] ], a[ ancestor[lv][1] ] );
					for(i = 0; i < len(height[lv] - 1) - 1; i++) {
						is_kado[lv][i + 1] = is_kado[lv][i] && is_kado[ ancestor[lv][i] ][i];
					}
				}
			}
			p = list_next[p];
		}
		get++;
	}
	
	
	for(i = 0; i < q; i++) {
		if(height[ u[i] ] < height[ v[i] ]) {
			int temp = u[i];
			u[i] = v[i];
			v[i] = temp;
		}
		
		int diff = height[ u[i] ] - height[ v[i] ];
		int s = up(u[i], diff);
		int t = v[i];
		int ans;
		if(s != t) {
			for(j = len(height[s]) - 1; 0 <= j; j--) {
				if(ancestor[s][j] != ancestor[t][j]) {
					s = ancestor[s][j];
					t = ancestor[t][j];
				}
			}
			int c = ancestor[s][0];
			int uu = ancestor[ u[i] ][0];
			int vv = ancestor[ v[i] ][0];
			
			ans = (
				isK(a[s], a[c], a[t]) &&
				isK(a[uu], a[u[i]], a[v[i]]) &&
				isK(a[vv], a[v[i]], a[u[i]]) &&
				is_kado_func(u[i], s) &&
				is_kado_func(v[i], t)
			);
		} else {
			int uu = ancestor[ u[i] ][0];
			int vv = up(u[i], diff - 1);
			
			ans = (
				isK(a[uu], a[u[i]], a[v[i]]) &&
				isK(a[vv], a[v[i]], a[u[i]]) &&
				is_kado_func(u[i], vv)
			);
		}
		
		printf("%s\n", ans ? "YES" : "NO");
	}
	
	return 0;
}
0