답안 #100890

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
100890 2019-03-15T03:37:40 Z E869120 동기화 (JOI13_synchronization) C++14
0 / 100
8000 ms 16544 KB
// クエリ平方分割 + bitset の (N^1.5 + N^2 / 64) で満点を狙う。

#include <bits/stdc++.h>
using namespace std;

const int Backet = 100;

int N, M, A[100009], B[100009], X[200009], D1[200009], D2[200009];
int num[100009], col[100009], colnum[100009], cnts, cntv;
bool used[100009], used2[100009], used3[100009], v[100009];
vector<int> G1[100009], G2[100009];

unsigned long long ptr[300009];

void dfs(int pos) {
	col[pos] = cnts;
	for (int i : G1[pos]) {
		if (col[i] >= 1) continue;
		dfs(i);
	}
}

void dfs1(int pos, int rev) {
	colnum[pos] = rev; used3[pos] = true;
	for (int i : G2[pos]) {
		if (used3[i] == true) continue;
		dfs1(i, rev);
	}
}

void solve(int l, int r) {
	for (int i = 1; i <= N; i++) { col[i] = 0; colnum[i] = 0; G1[i].clear(); }
	for (int i = 1; i <= N - 1; i++) used2[i] = used[i];
	for (int i = l; i <= r; i++) used2[X[i]] = false;
	
	for (int i = 1; i <= N - 1; i++) {
		if (used2[i] == false) continue;
		G1[A[i]].push_back(B[i]);
		G1[B[i]].push_back(A[i]);
	}
	
	cnts = 0;
	
	for (int i = 1; i <= N; i++) {
		if (col[i] >= 1) continue;
		cnts++; dfs(i);
	}
	for (int i = 1; i <= N; i++) colnum[col[i]] = num[i];
	
	vector<int>E;
	for (int i = l; i <= r; i++) { E.push_back(col[A[X[i]]]); E.push_back(col[B[X[i]]]); }
	sort(E.begin(), E.end()); E.erase(unique(E.begin(), E.end()), E.end());
	
	for (int i = l; i <= r; i++) {
		for (int j = 0; j < E.size(); j++) { used3[E[j]] = false; G2[E[j]].clear(); }
		
		// グラフに現在の辺を貼る
		for (int j = l; j <= i; j++) {
			bool e = used[X[j]]; if (X[j] == X[i]) e ^= true;
			if (e == false) continue;
			
			int pos = X[j];
			G2[col[A[pos]]].push_back(col[B[pos]]);
			G2[col[B[pos]]].push_back(col[A[pos]]);
		}
		
		int pos = X[i];
		if (used[pos] == false) {
			// 結合する場合 : D1 と D2 を結合して D1 にする
			D1[i] = colnum[col[A[pos]]];
			D2[i] = colnum[col[B[pos]]];
			dfs1(col[A[pos]], D1[i]);
			v[i] = false;
		}
		if (used[pos] == true) {
			// 分離する場合: D1 を D2 にコピーする
			D1[i] = colnum[col[A[pos]]];
			D2[i] = cntv + 1; cntv++;
			dfs1(col[B[pos]], cntv);
			v[i] = true;
		}
		used[pos] ^= true;
	}
	
	for (int i = 1; i <= N; i++) num[i] = colnum[col[i]];
}

int ans[100009];

int main() {
	int Q;
	scanf("%d%d%d", &N, &M, &Q);
	for (int i = 1; i <= N - 1; i++) scanf("%d%d", &A[i], &B[i]);
	for (int i = 1; i <= M; i++) scanf("%d", &X[i]);
	for (int i = 1; i <= N; i++) num[i] = i;
	
	cntv = N;
	
	// クエリ平方分割パート
	for (int i = 1; i <= M; i += Backet) {
		int L = i, R = i + Backet - 1; if (R > M) R = M;
		
		solve(L, R);
	}
	
	// ビットセットパート
	int BASE = 64;
	for (int i = 1; i <= N; i += BASE) {
		int L = i, R = i + (BASE - 1); if (R >= N) R = N;
		for (int j = 1; j <= cntv; j++) ptr[j] = 0;
		for (int j = L; j <= R; j++) ptr[j] += (1LL << (j - L));
		
		for (int j = 1; j <= M; j++) {
			if (v[j] == false) ptr[D1[j]] |= ptr[D2[j]];
			if (v[j] == true) ptr[D2[j]] = ptr[D1[j]];
		}
		
		for (int j = 1; j <= M; j++) ans[j] += __builtin_popcountll(ptr[num[j]]);
	}
	for (int j = 1; j <= Q; j++) {
		int cc; scanf("%d", &cc);
		printf("%d\n", ans[cc]);
	}
	return 0;
}

Compilation message

synchronization.cpp: In function 'void solve(int, int)':
synchronization.cpp:55:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (int j = 0; j < E.size(); j++) { used3[E[j]] = false; G2[E[j]].clear(); }
                   ~~^~~~~~~~~~
synchronization.cpp: In function 'int main()':
synchronization.cpp:92:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d%d%d", &N, &M, &Q);
  ~~~~~^~~~~~~~~~~~~~~~~~~~~~
synchronization.cpp:93:40: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  for (int i = 1; i <= N - 1; i++) scanf("%d%d", &A[i], &B[i]);
                                   ~~~~~^~~~~~~~~~~~~~~~~~~~~~
synchronization.cpp:94:36: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  for (int i = 1; i <= M; i++) scanf("%d", &X[i]);
                               ~~~~~^~~~~~~~~~~~~
synchronization.cpp:121:16: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   int cc; scanf("%d", &cc);
           ~~~~~^~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 8 ms 5120 KB Output is correct
2 Correct 7 ms 5120 KB Output is correct
3 Correct 9 ms 5120 KB Output is correct
4 Correct 8 ms 5120 KB Output is correct
5 Correct 7 ms 5120 KB Output is correct
6 Correct 9 ms 5248 KB Output is correct
7 Correct 119 ms 6652 KB Output is correct
8 Correct 147 ms 6548 KB Output is correct
9 Correct 122 ms 6492 KB Output is correct
10 Execution timed out 8061 ms 13428 KB Time limit exceeded
11 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 5514 ms 16544 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 7 ms 5120 KB Output is correct
2 Correct 6 ms 5120 KB Output is correct
3 Incorrect 7 ms 5120 KB Output isn't correct
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 8009 ms 14588 KB Time limit exceeded
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 6 ms 5120 KB Output is correct
2 Correct 6 ms 5120 KB Output is correct
3 Correct 6 ms 5120 KB Output is correct
4 Incorrect 6 ms 5120 KB Output isn't correct
5 Halted 0 ms 0 KB -