답안 #68576

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
68576 2018-08-17T11:30:44 Z cdemirer 관광지 (IZhO14_shymbulak) C++17
70 / 100
335 ms 40792 KB
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> ii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ii> vii;
typedef vector<vii> vvii;
typedef pair<double, double> dodo;
typedef pair<ll, ll> llp;
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)


int N;
vvi edges;

vi circle;
bool onCircle[200000] = {0};
vvi distantNodes;
vi distantDist;
vi distantSize;

int parent[200000];
bool vis[200000] = {0};
void fcircle(int x) {
	vis[x] = true;
	for (int i = 0; i < edges[x].size(); i++) {
		int y = edges[x][i];
		if (y == parent[x]) continue;
		if (vis[y]) {
			int q = x;
			while (q != y) {
				circle.pb(q);
				q = parent[q];
			}
			circle.pb(y);
			return;
		}
		parent[y] = x;
		fcircle(y);
		if (!circle.empty()) break;
	}
}

int fdistance(int x) {
	int ret = 0;
	for (int i = 0; i < edges[x].size(); i++) {
		int y = edges[x][i];
		if (y == parent[x]) continue;
		if (onCircle[y]) continue;
		parent[y] = x;
		ret = max(ret, 1 + fdistance(y));
	}
	return ret;
}
int fsize(int x, int dst) {
	if (dst == 0) return 1;
	int ret = 0;
	for (int i = 0; i < edges[x].size(); i++) {
		int y = edges[x][i];
		if (y == parent[x]) continue;
		if (onCircle[y]) continue;
		parent[y] = x;
		ret += fsize(y, dst-1);
	}
	return ret;
}

typedef struct NodeT {
	int llim, rlim;
	int value, valsz, up;
} Node;
const int segsz = 524288;
const int offset = segsz/2;
Node seg[segsz];
#define left(x) ((x)*2)
#define right(x) ((x)*2+1)
void seginit() {
	for (int i = offset; i < segsz; i++) {
		seg[i].llim = seg[i].rlim = i-offset;
		seg[i].value = 0;
	}
	for (int i = offset-1; i > 0; i--) {
		seg[i].llim = seg[left(i)].llim;
		seg[i].rlim = seg[right(i)].rlim;
		seg[i].value = 0;
	}
}
// setPointWithSecondValue --> Can be used only before any normal update calls
void setPointWithSecondValue(int pos, int val1, int val2) {
	pos += offset;
	seg[pos].value = val1;
	seg[pos].valsz = val2;
	pos /= 2;
	while (pos) {
		int mx = max(seg[left(pos)].value, seg[right(pos)].value);
		int sz = 0;
		if (seg[left(pos)].value == mx) sz += seg[left(pos)].valsz;
		if (seg[right(pos)].value == mx) sz += seg[right(pos)].valsz;
		seg[pos].value = mx;
		seg[pos].valsz = sz;
		pos /= 2;
	}
}
void push(int x) {
	seg[x].value += seg[x].up;
	if (x < offset) {
		seg[left(x)].up += seg[x].up;
		seg[right(x)].up += seg[x].up;
	}
	seg[x].up = 0;
}
ii get(int x, int l, int r) {
	push(x);
	int llim = seg[x].llim, rlim = seg[x].rlim;
	int mid = (llim+rlim)/2;
	if (l == llim && r == rlim) return mp(seg[x].value, seg[x].valsz);
	else if (l > mid) return get(right(x), l, r);
	else if (r <= mid) return get(left(x), l, r);
	else {
		ii a = get(left(x), l, mid);
		ii b = get(right(x), mid+1, r);
		int mx = max(a.first, b.first);
		int sz = 0;
		if (a.first == mx) sz += a.second;
		if (b.first == mx) sz += b.second;
		return mp(mx, sz);
	}
}
void update(int x, int l, int r, int u) {
	push(x);
	int llim = seg[x].llim, rlim = seg[x].rlim;
	int mid = (llim+rlim)/2;
	if (l == llim && r == rlim) {
		seg[x].up += u;
		push(x);
		return;
	}
	else if (l > mid) update(right(x), l, r, u);
	else if (r <= mid) update(left(x), l, r, u);
	else {
		update(left(x), l, mid, u);
		update(right(x), mid+1, r, u);
	}
	ii a = get(left(x), llim, mid);
	ii b = get(right(x), mid+1, rlim);
	int mx = max(a.first, b.first);
	int sz = 0;
	if (a.first == mx) sz += a.second;
	if (b.first == mx) sz += b.second;
	seg[x].value = mx;
	seg[x].valsz = sz;
}
void debugpush(int x) {
	push(x);
	if (x < offset) {
		debugpush(left(x));
		debugpush(right(x));
	} else {
		seg[x].value += seg[x].up;
		seg[x].up = 0;
	}
}

ll dfsanswer = -1;
ll dfsanswersize = 0;
ll dp[200000][2];
void dfs(int x) {
	vii childs;
	ll q;
	for (int i = 0; i < edges[x].size(); i++) {
		int y = edges[x][i];
		if (y == parent[x]) continue;
		if (onCircle[y]) continue;
		parent[y] = x;
		dfs(y);
		childs.pb(mp(dp[y][0], dp[y][1]));
		q = y;
	}
	if (childs.size() == 0) {
		dp[x][0] = 1;
		dp[x][1] = 1;
	}
	else if (childs.size() == 1) {
		dp[x][0] = dp[q][0] + 1;
		dp[x][1] = dp[q][1];
	}
	else {
		sort(childs.begin(), childs.end());
		reverse(childs.begin(), childs.end());
		int mx = childs[0].first;
		int mx2 = -1;
		for (int i = 0; i < childs.size(); i++) {
			if (childs[i].first != mx) mx2 = max(mx2, childs[i].first);
		}
		ll ans = 0;
		ll presz = 0;
		for (int i = 0; i < childs.size(); i++) {
			if (mx == childs[i].first) {
				ans += presz * childs[i].second;
				presz += childs[i].second;
			}
		}
		int len = 2*mx;
		if (!ans) {
			assert(mx2 != -1);
			for (int i = 0; i < childs.size(); i++) {
				if (mx2 == childs[i].first) {
					ans += presz * childs[i].second;
				}
			}
			len = mx + mx2;
		}
		
		if (len == dfsanswer) {
			dfsanswersize += ans;
		} else if (len > dfsanswer) {
			dfsanswer = len;
			dfsanswersize = ans;
		}
		dp[x][0] = mx + 1;
		dp[x][1] = presz;
	}
}
llp solveTree(int st) {
	parent[st] = -1;
	dfs(st);
	return mp(dfsanswer, dfsanswersize);
}


int main(int argc, char **argv) {
	ios_base::sync_with_stdio(0);
	cin.tie(0);

	cin >> N; edges.resize(N);
	for (int i = 0; i < N; i++) {
		int a, b; cin >> a >> b; a--; b--;
		edges[a].pb(b); edges[b].pb(a);
	}
	parent[0] = -1;
	fcircle(0);
	for (int i = 0; i < circle.size(); i++) onCircle[circle[i]] = true;
	int circlen = circle.size();
	
	distantDist.resize(circle.size());
	distantSize.resize(circle.size());
	for (int i = 0; i < circle.size(); i++) {
		parent[circle[i]] = -1;
		distantDist[i] = fdistance(circle[i]);
		parent[circle[i]] = -1;
		distantSize[i] = fsize(circle[i], distantDist[i]);
	}
	
	seginit();
		
	for (int i = 0; i < circle.size(); i++) {
		//update(1, i, i, distantDist[i] + min(i, circlen-i));
		setPointWithSecondValue(i, distantDist[i] + min(i, circlen-i), distantSize[i]);
	}
	
	/*for (int i = 0; i < circle.size(); i++) {
		cerr << circle[i] << " ";
	} cerr << endl;
	for (int i = 0; i < circle.size(); i++) {
		//cerr << seg[offset+i].value << " ";
		cerr << distantDist[i] << " ";
	} cerr << endl;
	for (int i = 0; i < circle.size(); i++) {
		//cerr << seg[offset+i].value << " ";
		cerr << distantSize[i] << " ";
	} cerr << endl;
	cerr << endl;*/
	
	/*cerr << "the initial segment:" << endl;
	for (int i = 0; i < circle.size(); i++) {
		cerr << seg[offset+i].value << " ";
		//cerr << distantDist[i] << " ";
	} cerr << endl;*/
	
	vector<ll> ans(circle.size());
	vi selected(circle.size());
	for (int i = 0; i < circle.size(); i++) {
		
		/*cerr << "i is: " << i << " and this is how the segment currently is:" << endl;
		debugpush(1); for (int i = 0; i < circle.size(); i++) {
			cerr << seg[offset+i].value << " ";
		} cerr << endl;*/
		
		if (circlen % 2 == 0) {
			int oppo = (i+circlen/2)%circlen;
			int ex1 = i;
			int ex2 = oppo;
			if (ex1 > ex2) swap(ex1, ex2);
			ii a = (ex1 != 0 ? get(1, 0, ex1-1) : mp(0, 0));
			ii b = (ex2-ex1>1 ? get(1, ex1+1, ex2-1) : mp(0, 0));
			ii c = (ex2 != circlen-1 ? get(1, ex2+1, circlen-1) : mp(0, 0));
			int maxfst = max(a.first, max(b.first, c.first));
			int sz = 0;
			if (a.first == maxfst) sz += a.second;
			if (b.first == maxfst) sz += b.second;
			if (c.first == maxfst) sz += c.second;
			ii o = get(1, oppo, oppo);
			if (maxfst >= o.first) {
				selected[i] = maxfst;
				ans[i] += (ll)distantSize[i]*(ll)sz;
			}
			if (o.first >= maxfst) {
				selected[i] = o.first;
				ans[i] += (ll)distantSize[i]*(ll)o.second*(2ll);
			}
		} else { // circlen % 2 == 1
			ii a = (i?get(1, 0, i-1):mp(0, 0));
			ii b = (i!=circlen-1?get(1, i+1, circlen-1):mp(0, 0));
			int maxfst = max(a.first, b.first);
			int sz = 0;
			if (a.first == maxfst) sz += a.second;
			if (b.first == maxfst) sz += b.second;
			selected[i] = maxfst;
			ans[i] = (ll)distantSize[i]*(ll)sz;
		}
		
		selected[i] += distantDist[i];
		
		/*cerr << "selected is set: " << selected[i] << endl;
		cerr << "ans is set: " << ans[i] << endl;
		cerr << endl;*/

		if (circlen % 2 == 0) {
			update(1, 0, circlen-1, 1);
			int l = i+1, r = i+circlen/2;
			if (r < circlen) {
				update(1, l, r, -2);
			} else if (l >= circlen) {
				l -= circlen, r -= circlen;
				update(1, l, r, -2);
			} else {
				update(1, l, circlen-1, -2);
				r -= circlen;
				update(1, 0, r, -2);
			}
		} else { // circlen % 2 == 1
			update(1, 0, circlen-1, 1);
			int l = i+1, r = i+circlen/2;
			if (r < circlen) {
				update(1, l, r, -2);
			} else if (l >= circlen) {
				l -= circlen, r -= circlen;
				update(1, l, r, -2);
			} else {
				update(1, l, circlen-1, -2);
				r -= circlen;
				update(1, 0, r, -2);
			}
			int x = i+circlen/2+1;
			if (x >= circlen) x -= circlen;
			update(1, x, x, -1);
		}
		
	}
	/*cerr << "the last of the segment:" << endl;
	debugpush(1); for (int i = 0; i < circle.size(); i++) {
		cerr << seg[offset+i].value << " ";
	} cerr << endl;*/
	
	int mxs = *(max_element(selected.begin(), selected.end()));
	ll answer = 0;
	for (int i = 0; i < circle.size(); i++) if (selected[i] == mxs) answer += ans[i];
	answer /= 2;

/*for (int i = 0; i < circle.size(); i++) {
	cerr << selected[i] << " ";
} cerr << endl;
for (int i = 0; i < circle.size(); i++) {
	cerr << ans[i] << " ";
} cerr << endl;*/
	
	
	// don't forget to check the furthest pairs inside one circle piece
	for (int i = 0; i < circle.size(); i++) {
		onCircle[circle[i]] = false;
		llp res = solveTree(circle[i]);
		if (res.first > mxs) {
			mxs = res.first;
			answer = res.second;
		} else if (res.first == mxs) {
			answer += res.second;
		}
		onCircle[circle[i]] = true;
	}
	
	cout << answer << endl;

	return 0;
}

Compilation message

shymbulak.cpp: In function 'void fcircle(int)':
shymbulak.cpp:28:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < edges[x].size(); i++) {
                  ~~^~~~~~~~~~~~~~~~~
shymbulak.cpp: In function 'int fdistance(int)':
shymbulak.cpp:48:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < edges[x].size(); i++) {
                  ~~^~~~~~~~~~~~~~~~~
shymbulak.cpp: In function 'int fsize(int, int)':
shymbulak.cpp:60:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < edges[x].size(); i++) {
                  ~~^~~~~~~~~~~~~~~~~
shymbulak.cpp: In function 'void dfs(int)':
shymbulak.cpp:172:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < edges[x].size(); i++) {
                  ~~^~~~~~~~~~~~~~~~~
shymbulak.cpp:194:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (int i = 0; i < childs.size(); i++) {
                   ~~^~~~~~~~~~~~~~~
shymbulak.cpp:199:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (int i = 0; i < childs.size(); i++) {
                   ~~^~~~~~~~~~~~~~~
shymbulak.cpp:208:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    for (int i = 0; i < childs.size(); i++) {
                    ~~^~~~~~~~~~~~~~~
shymbulak.cpp: In function 'int main(int, char**)':
shymbulak.cpp:244:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < circle.size(); i++) onCircle[circle[i]] = true;
                  ~~^~~~~~~~~~~~~~~
shymbulak.cpp:249:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < circle.size(); i++) {
                  ~~^~~~~~~~~~~~~~~
shymbulak.cpp:258:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < circle.size(); i++) {
                  ~~^~~~~~~~~~~~~~~
shymbulak.cpp:284:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < circle.size(); i++) {
                  ~~^~~~~~~~~~~~~~~
shymbulak.cpp:369:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < circle.size(); i++) if (selected[i] == mxs) answer += ans[i];
                  ~~^~~~~~~~~~~~~~~
shymbulak.cpp:381:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < circle.size(); i++) {
                  ~~^~~~~~~~~~~~~~~
shymbulak.cpp: In function 'void dfs(int)':
shymbulak.cpp:186:21: warning: 'q' may be used uninitialized in this function [-Wmaybe-uninitialized]
   dp[x][0] = dp[q][0] + 1;
              ~~~~~~~^
# 결과 실행 시간 메모리 Grader output
1 Correct 11 ms 10616 KB Output is correct
2 Correct 9 ms 10616 KB Output is correct
3 Correct 10 ms 10668 KB Output is correct
4 Correct 10 ms 10668 KB Output is correct
5 Correct 10 ms 10708 KB Output is correct
6 Incorrect 10 ms 10780 KB Output isn't correct
7 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 13 ms 10908 KB Output is correct
2 Correct 11 ms 10908 KB Output is correct
3 Correct 12 ms 10964 KB Output is correct
4 Correct 11 ms 10964 KB Output is correct
5 Correct 12 ms 11372 KB Output is correct
6 Correct 13 ms 11376 KB Output is correct
7 Correct 13 ms 11376 KB Output is correct
8 Correct 14 ms 11376 KB Output is correct
9 Correct 12 ms 11376 KB Output is correct
10 Correct 16 ms 11376 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 108 ms 18092 KB Output is correct
2 Correct 108 ms 19824 KB Output is correct
3 Correct 217 ms 25196 KB Output is correct
4 Correct 95 ms 25196 KB Output is correct
5 Correct 64 ms 25196 KB Output is correct
6 Correct 335 ms 31332 KB Output is correct
7 Correct 165 ms 31332 KB Output is correct
8 Correct 157 ms 37328 KB Output is correct
9 Correct 129 ms 38296 KB Output is correct
10 Correct 137 ms 38888 KB Output is correct
11 Correct 156 ms 39984 KB Output is correct
12 Correct 191 ms 40792 KB Output is correct