Submission #343383

# Submission time Handle Problem Language Result Execution time Memory
343383 2021-01-03T20:31:51 Z emil_physmath Shymbulak (IZhO14_shymbulak) C++17
0 / 100
114 ms 15852 KB
//#define STRESS
#include <iostream>
#include <random>
#include <algorithm>
#include <vector>
#include <chrono>
using namespace std;
using llong = long long;
#ifdef MANSON
#define BUGO(x) cerr << #x << " = " << (x) << '\n';
#define BUGOARR(a) { cerr << #a << ": "; for (auto i: a) cerr << i << ' '; cerr << '\n'; }
#else
#define BUGO(x) ;
#define BUGOARR(a) {}
#endif
using llong = long long;
using uint = unsigned int;
using ullong = unsigned long long;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
inline int rnd(int l, int r) { return uniform_int_distribution<int>(l, r)(rng); }
inline llong rndll(llong l, llong r) { return uniform_int_distribution<llong>(l, r)(rng); }

namespace Brutos
{

    pair<int, int> answer(0, 1);
    vector<int> nei[200001];
    pair<int, int> tx[800000], ty[800000];

    template<typename T>
    inline T Comb2(T x) { return ((x - (T)1) * x) / (T)2; }
    template<class T1, class T2>
    ostream& operator<<(ostream& ostr, const pair<T1, T2>& a)
    {
        return ostr << "{" << a.first << ", " << a.second << "}";
    }
    void Add(pair<int, int>* a, const pair<int, int>& rhs)
    {
        if (rhs.first > a->first)
            *a = rhs;
        else if (rhs.first == a->first)
            a->second += rhs.second;
    }
    namespace Decomp
    {
        bool used[200001];
        bool root[200001];
        pair<int, int> ray[200001];
        vector<int> line;
        int FindCycle(int v, int par)
        {
            used[v] = true;
            for (int to: nei[v])
            {
                if (to == par) continue;
                if (used[to])
                {
                    line.push_back(v);
                    root[v] = true;
                    return to;
                }
                if (int ret = FindCycle(to, v))
                {
                    line.push_back(v);
                    root[v] = true;
                    if (v == ret)
                        return 0;
                    return ret;
                }
            }
            return 0;
        }
        void DFS(int v, int par)
        {
            // cerr << "v: " << v << "\tpar: " << par << endl;
            ray[v] = make_pair(0, 1);
            for (int to: nei[v])
                if (to != par && !root[to])
                {
                    DFS(to, v);
                    pair<int, int> p = ray[to];
                    ++p.first;
                    Add(ray + v, p);
                }
        }
        void AddWays(int v, int par)
        {
            vector<pair<int, int>> chld;
            chld.reserve(nei[v].size());
            for (int to: nei[v])
                if (to != par && !root[to])
                {
                    AddWays(to, v);
                    chld.push_back({ray[to].first + 1, ray[to].second});
                }
            if (chld.size() < 2)
                return;
            sort(chld.begin(), chld.end(), greater<pair<int, int>>());
            int i = 2;
            while (i < chld.size() && chld[i].first == chld[i - 1].first)
                ++i;
            if (i < chld.size()) chld.erase(chld.begin() + i, chld.end());
            /*cerr << "v: " << v << "`   chld: ";
            for (auto it: chld)
                cerr << it << ' ';
            cerr << endl;*/
            if (chld[0].first == chld[1].first)
            {
                pair<int, int> cur = {2 * chld[0].first, 0};
                int sum = 0;
                for (const pair<int, int>& p: chld)
                {
                    cur.second -= Comb2(p.second);
                    // if (v == 1)
                        // cerr << "delta -" << Comb2(p.second) << endl;
                    sum += p.second;
                }
                cur.second += Comb2(sum);
                // if (v == 1)
                    // cerr << "v: 1, cur: " << cur << endl;
                Add(&answer, cur);
            }
            else
            {
                int sum = 0;
                for (int i = 1; i < chld.size(); ++i)
                    sum += chld[i].second;
                pair<int, int> cur = {chld[0].first + chld[1].first, chld[0].second * sum};
                Add(&answer, cur);
            }
        }
        void Decompose(vector<pair<int, int>>* res)
        {
            FindCycle(1, -1);
    #ifdef DEBUG
            cerr << line.size() << endl;
            for (int v: line)
                cerr << v << ' ';
            cerr << '\n';
    #endif
            res->resize(line.size());
            for (int i = 0; i < line.size(); ++i)
            {
                DFS(line[i], -1);
                AddWays(line[i], -1);
                (*res)[i] = ray[line[i]];
    #ifdef DEBUG
                cerr << line[i] << ": " << (*res)[i] << '\n';
    #endif
            }
        }
    };
    void Build(pair<int, int>* t, int v, int vl, int vr, const vector<pair<int, int>>& a)
    {
        if (vl == vr)
        {
            t[v] = a[vr];
            return;
        }
        int vm = (vl + vr) / 2;
        Build(t, v * 2, vl, vm, a);
        Build(t, v * 2 + 1, vm + 1, vr, a);
        t[v] = t[v * 2];
        Add(t + v, t[v * 2 + 1]);
    }
    pair<int, int> Max(pair<int, int>* t, int v, int vl, int vr, int l, int r)
    {
        if (vl == l && vr == r)
            return t[v];
        int vm = (vl + vr) / 2;
        if (r <= vm)
            return Max(t, v * 2, vl, vm, l, r);
        else if (l > vm)
            return Max(t, v * 2 + 1, vm + 1, vr, l, r);
        pair<int, int> res = Max(t, v * 2, vl, vm, l, vm);
        Add(&res, Max(t, v * 2 + 1, vm + 1, vr, vm + 1, r));
        return res;
    }
    #ifdef ALL_LL
    #undef int
    #endif // ALL_LL
    int Solve(int nodes, const vector<pair<int, int>>& edges)
    #ifdef ALL_LL
    #define int llong
    #endif // ALL_LL
    {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        for (auto [u, v]: edges)
        {
            nei[u].push_back(v);
            nei[v].push_back(u);
        }
        vector<pair<int, int>> a;
        Decomp::Decompose(&a);
        int n = a.size();
        vector<pair<int, int>> x(n), y(n);
        for (int i = 0; i < n; ++i)
        {
            x[i] = {i + a[i].first, a[i].second};
            y[i] = {n - i + a[i].first, a[i].second};
    #ifdef DEBUG
            cerr << "i: " << i << ": x = " << x[i] << "   y = " << y[i] << "   a[i] = " << a[i] << endl;
    #endif
        }
        Build(tx, 1, 0, n - 1, x);
        Build(ty, 1, 0, n - 1, y);
        for (int l = 0; l + 1 < n; ++l)
        {
            int s = l + 1;
            int e = l + n / 2;
            e = min(e, n - 1);
            if (s <= e)
            {
                pair<int, int> mx = Max(tx, 1, 0, n - 1, s, e);
                Add(&answer, {mx.first - l + a[l].first, mx.second * a[l].second});
            }
            s = l + (n + 1) / 2;
            e = n - 1;
            if (s <= e)
            {
                pair<int, int> mx = Max(ty, 1, 0, n - 1, s, e);
                Add(&answer, {mx.first + l + a[l].first, mx.second * a[l].second});
            }
        }
        // cerr << answer.first<< ' ';
        return answer.second;
    }
    /*
    19
    6 2
    6 4
    1 4
    1 5
    2 3
    6 7
    7 8
    7 9
    6 10
    10 11
    11 12
    8 13
    9 14
    3 15
    10 16
    16 17
    16 18
    2 19
    4 19

    6
    6 2
    6 4
    1 4
    1 5
    2 3
    2 4
    */
}

const int N = 200'002;
int c[N], used[N];
vector<int> g[N], h;
struct el {
	int l, q;
}mx1[N], mx2[N], dp[N];
vector<el> a;
el operator+(const el& a, const el& b) {
	return { a.l,a.q + b.q };
}
bool operator<(const el& a, const el& b) {
	if (a.l == b.l)
		return a.q < b.q;
	return a.l < b.l;
}
int Dfs(int v, int p)
{
	used[v] = 1;
	for(int to: g[v])
		if (to != p) {
			if (used[to]) {
				c[v] = 1;
				h.push_back(v);
				return to;
			}
			int x = Dfs(to, v);
			if (x != 0) {
				c[v] = 1;
				h.push_back(v);
				return (x == v) ? 0 : x;
			}
		}
	return 0;
}
void DfsDp(int v, int p) {
	for (int to : g[v])
		if (to != p && c[to] != 1) {
			DfsDp(to, v);
			el x = { mx1[to].l + 1, mx1[to].q };
			if (x.l > mx1[v].l) {
				mx2[v] = mx1[v];
				mx1[v] = x;
			}
			else if (x.l == mx1[v].l)
				mx1[v].q += x.q;
			else if (x.l > mx2[v].l)
				mx2[v] = x;
			else if (x.l == mx2[v].l)
				mx2[v].q += x.q;
			if (dp[v].l == dp[to].l)
				dp[v] = dp[v] + dp[to];
			if (dp[v].l < dp[to].l)
				dp[v] = dp[to];
		}
	if (!mx1[v].l)
		mx1[v] = {0, 1};
	if (!mx2[v].l)
		mx2[v] = {0, 1};
    if (v == 1&&0)
    {
        cerr << "v = 1\n";
        cerr << mx1[v].l << ' ' << mx1[v].q << '\n';
        cerr << mx2[v].l << ' ' << mx2[v].q << '\n';
    }
	el x;
	int sum = 0;
	for (int to : g[v])
		if (to != p && c[to] != 1)
			if (mx1[to].l + 1 == mx1[v].l)
				sum += (mx1[v].q - mx1[to].q) * mx1[to].q;
	sum /= 2;
    if (v == 1&&0)
        cerr << "sum: " << sum << '\n';
	x = { sum ? el{2 * mx1[v].l, sum} : el{mx1[v].l + mx2[v].l, mx1[v].q * mx2[v].q} };
	if (x.l == dp[v].l && x.l != 0)
		dp[v].q += x.q;
	dp[v] = max(dp[v], x);
    if (!dp[v].l)
        dp[v] = {0, 1};
}
el t[4 * N];
void Build(int v, int vl, int vr)
{
	if (vl == vr)
	{
		t[v] = {a[vl].l, a[vl].q};
		return;
	}
	int m = (vl + vr) / 2;
	Build(v * 2, vl, m);
	Build(v * 2 + 1, m + 1, vr);
	if (t[v * 2].l == t[v * 2 + 1].l)
	{
		t[v].l = t[v * 2].l;
		t[v].q = t[v * 2].q + t[v * 2 + 1].q;
	}
	else t[v] = max(t[v * 2], t[v * 2 + 1]);
}
el GetMax(int v, int vl, int vr, int l, int r)
{
	if (vl == l && vr == r)
		return t[v];
	int m = (vl + vr) / 2;
	el r1, r2;
	if (r <= m)
		return GetMax(v * 2, vl, m, l, r);
	if (l > m)
		return GetMax(v * 2 + 1, m + 1, vr, l, r);
	r1 = GetMax(v * 2, vl, m, l, m);
	r2 = GetMax(v * 2 + 1, m + 1, vr, m + 1, r);
	if (r1.l == r2.l)
		return {r1.l, r1.q + r2.q};
	return max(r1, r2);
}
int main()
{
	int n;
	cin >> n;
#ifdef STRESS
    vector<pair<int, int>> edges;
    for (int v = 2; v <= n; ++v)
    {
        int u = rnd(1, v - 1);
        cout << u << ' ' << v << '\n';
        edges.push_back({u, v});
		g[u].push_back(v);
		g[v].push_back(u);
    }
    do {
        int v = rnd(1, n);
        int u = rnd(1, n);
        if (u == v || count(edges.begin(), edges.end(), pair{u, v}) || count(edges.begin(), edges.end(), pair{v, u})) continue;
        edges.push_back({u, v});
        g[u].push_back(v);
        g[v].push_back(u);
        cout << u << ' ' << v << '\n';
        break;
    } while (true);
    cout << "Brutos: " << Brutos::Solve(n, edges) << endl;
#else
	for (int i = 0; i < n; i++) {
		int u, v;
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
#endif
	Dfs(1, -1);
	el ans = { 0,1 };
	for (int i = 1; i <= n; i++) {
		if (c[i]) {
			DfsDp(i, -1);
		}
	//	cerr << "dp" << i << ' ' << dp[i].l << ' ' << dp[i].q << '\n';
		//cerr << "ans " << ans.l << ' ' << ans.q << '\n';
	}
for (int i = 1; i <= n; i++)
        if (dp[i].l == ans.l)
            ans.q += dp[i].q;
        else
            ans = max(ans, dp[i]);
	for (int v : h)	{
	//	cerr << v << ' ';
		a.push_back(mx1[v]);
	}
	//cerr << '\n';
	for (int v : h) {
		//cerr << mx1[v].l << ' ';
		a.push_back(mx1[v]);
	}
	//cerr << '\n';
	//for (auto v : a)
		//cerr << v.l << ' ';
	//cerr << '\n';
	n = (int)a.size() / 2;
	for (int i = 0; i < a.size(); i++) {
		a[i].l += i;
	//	cerr << a[i].l << ' ' << a[i].q << '\n';
		//if (a[i].q == 0)a[i].q++;
	}
	//cerr << '\n';
	Build(1, 0, (int)a.size() - 1);
	//cerr << "ans " << ans.l << ' ' << ans.q << '\n';
	for (int i = 0; i < n; i++) {
		el cur = GetMax(1, 0, 2 * n - 1, i + 1, i + n / 2);
		//cerr << i + 1 << "..." << i + n / 2 << "..." << cur.l << ' ' << cur.q << '\n';
		cur.l -= 2 * i;
		cur.l += a[i].l;
		cur.q *= a[i].q;
		//cerr << i + 1 << "..." << i + n / 2 << "..." << cur.l << ' ' << cur.q << "\n\n";
		if (cur.l == ans.l)
			ans.q += cur.q;
		else
            ans = max(ans, cur);
	}
	cout << ans.q << '\n';
	return 0;
}




Compilation message

shymbulak.cpp: In function 'void Brutos::Decomp::AddWays(int, int)':
shymbulak.cpp:100:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  100 |             while (i < chld.size() && chld[i].first == chld[i - 1].first)
      |                    ~~^~~~~~~~~~~~~
shymbulak.cpp:102:19: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  102 |             if (i < chld.size()) chld.erase(chld.begin() + i, chld.end());
      |                 ~~^~~~~~~~~~~~~
shymbulak.cpp:126:35: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  126 |                 for (int i = 1; i < chld.size(); ++i)
      |                                 ~~^~~~~~~~~~~~~
shymbulak.cpp: In function 'void Brutos::Decomp::Decompose(std::vector<std::pair<int, int> >*)':
shymbulak.cpp:142:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  142 |             for (int i = 0; i < line.size(); ++i)
      |                             ~~^~~~~~~~~~~~~
shymbulak.cpp: In function 'void DfsDp(int, int)':
shymbulak.cpp:332:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
  332 |     if (v == 1&&0)
      |     ^~
shymbulak.cpp:334:2: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
  334 |  x = { sum ? el{2 * mx1[v].l, sum} : el{mx1[v].l + mx2[v].l, mx1[v].q * mx2[v].q} };
      |  ^
shymbulak.cpp: In function 'int main()':
shymbulak.cpp:417:1: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
  417 | for (int i = 1; i <= n; i++)
      | ^~~
shymbulak.cpp:422:2: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
  422 |  for (int v : h) {
      |  ^~~
shymbulak.cpp:436:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<el>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  436 |  for (int i = 0; i < a.size(); i++) {
      |                  ~~^~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 7 ms 9708 KB Output is correct
2 Correct 6 ms 9708 KB Output is correct
3 Correct 7 ms 9708 KB Output is correct
4 Correct 7 ms 9708 KB Output is correct
5 Correct 7 ms 9708 KB Output is correct
6 Correct 7 ms 9708 KB Output is correct
7 Correct 7 ms 9708 KB Output is correct
8 Correct 8 ms 9708 KB Output is correct
9 Correct 7 ms 9708 KB Output is correct
10 Correct 7 ms 9708 KB Output is correct
11 Correct 7 ms 9708 KB Output is correct
12 Correct 7 ms 9708 KB Output is correct
13 Incorrect 7 ms 9836 KB Output isn't correct
14 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 7 ms 9964 KB Output is correct
2 Correct 7 ms 9836 KB Output is correct
3 Correct 7 ms 9836 KB Output is correct
4 Correct 8 ms 9836 KB Output is correct
5 Correct 10 ms 10092 KB Output is correct
6 Correct 10 ms 10092 KB Output is correct
7 Correct 10 ms 10092 KB Output is correct
8 Incorrect 10 ms 10092 KB Output isn't correct
9 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 107 ms 15340 KB Output is correct
2 Incorrect 114 ms 15852 KB Output isn't correct
3 Halted 0 ms 0 KB -