Submission #68578

# Submission time Handle Problem Language Result Execution time Memory
68578 2018-08-17T11:34:28 Z cdemirer Shymbulak (IZhO14_shymbulak) C++17
100 / 100
318 ms 28892 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;
			}
		}
		ll sz2 = 0;
		int len = 2*mx;
		if (!ans) {
			assert(mx2 != -1);
			for (int i = 0; i < childs.size(); i++) {
				if (mx2 == childs[i].first) {
					sz2 += childs[i].second;
				}
			}
			ans += presz * sz2;
			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;
	dfsanswer = -1;
	dfsanswersize = 0;
	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:209: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:248: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:253:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < circle.size(); i++) {
                  ~~^~~~~~~~~~~~~~~
shymbulak.cpp:262:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < circle.size(); i++) {
                  ~~^~~~~~~~~~~~~~~
shymbulak.cpp:288:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < circle.size(); i++) {
                  ~~^~~~~~~~~~~~~~~
shymbulak.cpp:373: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:385: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;
              ~~~~~~~^
# Verdict Execution time Memory Grader output
1 Correct 10 ms 10616 KB Output is correct
2 Correct 10 ms 10728 KB Output is correct
3 Correct 12 ms 10764 KB Output is correct
4 Correct 12 ms 10764 KB Output is correct
5 Correct 12 ms 10764 KB Output is correct
6 Correct 10 ms 10764 KB Output is correct
7 Correct 10 ms 10788 KB Output is correct
8 Correct 9 ms 10916 KB Output is correct
9 Correct 10 ms 10916 KB Output is correct
10 Correct 10 ms 10916 KB Output is correct
11 Correct 10 ms 10916 KB Output is correct
12 Correct 12 ms 10916 KB Output is correct
13 Correct 10 ms 10916 KB Output is correct
14 Correct 10 ms 10916 KB Output is correct
15 Correct 12 ms 10916 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 15 ms 10944 KB Output is correct
2 Correct 12 ms 10944 KB Output is correct
3 Correct 12 ms 10988 KB Output is correct
4 Correct 11 ms 10988 KB Output is correct
5 Correct 12 ms 11244 KB Output is correct
6 Correct 12 ms 11468 KB Output is correct
7 Correct 12 ms 11468 KB Output is correct
8 Correct 13 ms 11468 KB Output is correct
9 Correct 17 ms 11468 KB Output is correct
10 Correct 13 ms 11468 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 120 ms 18208 KB Output is correct
2 Correct 149 ms 18780 KB Output is correct
3 Correct 318 ms 23028 KB Output is correct
4 Correct 64 ms 23028 KB Output is correct
5 Correct 67 ms 23028 KB Output is correct
6 Correct 296 ms 24512 KB Output is correct
7 Correct 218 ms 24512 KB Output is correct
8 Correct 134 ms 26212 KB Output is correct
9 Correct 134 ms 26368 KB Output is correct
10 Correct 193 ms 27012 KB Output is correct
11 Correct 200 ms 28124 KB Output is correct
12 Correct 160 ms 28892 KB Output is correct