Submission #707297

# Submission time Handle Problem Language Result Execution time Memory
707297 2023-03-08T18:08:19 Z Nhoksocqt1 Tropical Garden (IOI11_garden) C++17
0 / 100
14 ms 25284 KB
#include<bits/stdc++.h>
#include "garden.h"
#include "gardenlib.h"
using namespace std;

#define inf 0x3f3f3f3f
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
#define sz(x) int((x).size())
#define fi first
#define se second
typedef long long ll;
typedef pair<int, int> ii;

template<class X, class Y>
	inline bool maximize(X &x, const Y &y) {return (x < y ? x = y, 1 : 0);}
template<class X, class Y>
	inline bool minimize(X &x, const Y &y) {return (x > y ? x = y, 1 : 0);}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int Random(int l, int r) {
    return uniform_int_distribution<int>(l, r)(rng);
}

const int MAXN = 150005;
const int MAXM = 300005;

struct Edge {
    int u, v;
} edge[MAXN];

struct Query {
    int K, pos;
} qr[2005];

vector<ii> adj[MAXN];
vector<int> adjp[MAXM], comp[MAXM], B[MAXM];
ii a[MAXM], b[MAXM], itOf[MAXM];
int h[MAXM], timeIn[MAXM], timeOut[MAXM], result[2005];
int firstToLoop[MAXM], firstInLoop[MAXM], loopOf[MAXM], posInComp[MAXM];
int deg[MAXM], pa[MAXM], idc[MAXM], idn[MAXN], numNode, numEdge, numQuery, lastNode;
bool dx[MAXM], ok[MAXM];

inline int getLeftNode(int id) {
    return (id >= numEdge) ? edge[id - numEdge].v : edge[id].u;
}

int timeIn0;
void preDfs(int u, int p) {
    timeIn[u] = ++timeIn0;
    if(ok[u])
        B[h[u]].push_back(timeIn[u]);

    for (int it = 0; it < int(adjp[u].size()); ++it) {
        int v(adjp[u][it]);
        if(v != p) {
            h[v] = 1 + h[u];
            preDfs(v, u);
        }
    }

    timeOut[u] = timeIn0;
}

void count_routes(int _N, int _M, int _P, int _R[][2], int _Q, int _G[]) {
    numNode = _N, numEdge = _M, lastNode = _P, numQuery = _Q;
    for (int i = 0; i < _M; ++i) {
        int u(_R[i][0]), v(_R[i][1]);
        edge[i] = {u, v};
        adj[u].push_back({v, i});
        adj[v].push_back({u, i});
    }

    for (int u = 0; u < numNode; ++u) {
        int id0 = adj[u][0].se;
        int id1 = (adj[u].size() > 1 ? adj[u][1].se : 1e9+7);
        bool type0 = (u == edge[adj[u][0].se].v);
        bool type1 = (adj[u].size() > 1 && (u == edge[adj[u][1].se].v));

        for (int it = 0; it < int(adj[u].size()); ++it) {
            int v(adj[u][it].fi), id(adj[u][it].se);
            bool type = !(u == edge[id].v);
            if(it == 0) {
                idn[u] = id + !type * numEdge;
                ok[idn[u]] = 1;
            }

            pa[id + type * numEdge] = (id != id0 || id1 >= 1e9+7) ? id0 + type0 * numEdge : id1 + type1 * numEdge;
            ++deg[pa[id + type * numEdge]];
        }
    }

    int numComp(0);
    for (int id = 0; id < 2 * numEdge; ++id) {
        if(deg[id] || dx[id])
            continue;

        vector<int> tmpn;
        int tmp(id);
        while(!dx[tmp]) {
            dx[tmp] = 1;
            tmpn.push_back(tmp);
            tmp = pa[tmp];
        }

        int szn(tmpn.size());
        for (int it = 0; it <= szn; ++it) {
            if(it == szn || tmpn[it] == tmp) {
                if(it < szn) {
                    for (int jt = it; jt < szn; ++jt) {
                        posInComp[tmpn[jt]] = jt - it;
                        comp[numComp].push_back(tmpn[jt]);
                        firstInLoop[tmpn[jt]] = tmpn[jt];
                        loopOf[tmpn[jt]] = szn - it;
                        firstToLoop[tmpn[jt]] = 0;
                        idc[tmpn[jt]] = numComp;
                    }

                    ++numComp;
                }

                if(it > 0) {
                    adjp[tmp].push_back(tmpn[it - 1]);
                    for (int jt = 0; jt < it; ++jt) {
                        posInComp[tmpn[jt]] = jt;
                        comp[numComp].push_back(tmpn[jt]);
                        firstToLoop[tmpn[jt]] = it - jt + firstToLoop[tmp];
                        firstInLoop[tmpn[jt]] = firstInLoop[tmp];
                        idc[tmpn[jt]] = numComp;
                        if(jt + 1 < it)
                            adjp[tmpn[jt + 1]].push_back(tmpn[jt]);
                    }

                    ++numComp;
                }

                break;
            }
        }
    }

    for (int id = 0; id < 2 * numEdge; ++id) {
        if(!deg[id] || dx[id])
            continue;

        int tmp(id);
        while(!dx[tmp]) {
            dx[tmp] = 1;
            posInComp[tmp] = comp[numComp].size();
            comp[numComp].push_back(tmp);
            idc[tmp] = numComp;
            firstToLoop[tmp] = 0;
            firstInLoop[tmp] = tmp;
            tmp = pa[tmp];
        }

        int szn(comp[numComp].size());
        for (int it = 0; it < szn; ++it)
            loopOf[comp[numComp][it]] = szn;

        ++numComp;
    }

    for (int id = 0; id < 2 * numEdge; ++id) {
        if(!timeIn[id])
            preDfs(id, -1);

        a[id] = {timeIn[id], id};
        b[id] = {timeOut[id], id};
    }

    for (int t = 0; t < numQuery; ++t)
        qr[t] = {_G[t], t};

    sort(qr, qr + numQuery, [](const Query &a, const Query &b) {
        return a.K < b.K;
    });

    sort(a, a + 2 * numEdge);
    sort(b, b + 2 * numEdge);

    for (int itn = 0; itn < 2 * numEdge; ++itn) {
        int id(a[itn].se);
        if(adjp[id].size() == 0 || getLeftNode(id) != lastNode)
            continue;

        for (int t = 0; t < numQuery; ++t) {
            int K(qr[t].K), pos(qr[t].pos);
            if(h[id] + K > 2 * numEdge || B[h[id] + K].empty())
                break;

            h[id] += K;
            int szB(B[h[id]].size());
            while(itOf[h[id]].fi < szB && B[h[id]][itOf[h[id]].fi] <= timeOut[id])
                ++itOf[h[id]].fi;

            result[pos] += itOf[h[id]].fi;
            h[id] -= K;
        }
    }

    for (int itn = 0; itn < 2 * numEdge; ++itn) {
        int id(b[itn].se);
        if(adjp[id].size() == 0 || getLeftNode(id) != lastNode)
            continue;

        for (int t = 0; t < numQuery; ++t) {
            int K(qr[t].K), pos(qr[t].pos);
            if(h[id] + K > 2 * numEdge || B[h[id] + K].empty())
                break;

            h[id] += K;
            int szB(B[h[id]].size());
            while(itOf[h[id]].se < szB && B[h[id]][itOf[h[id]].se] < timeIn[id])
                ++itOf[h[id]].se;

            result[pos] -= itOf[h[id]].se;
            h[id] -= K;
        }
    }

    for (int t = 0; t < numQuery; ++t) {
        int K(qr[t].K), pos(qr[t].pos);
        for (int u = 0; u < numNode; ++u) {
            if(firstToLoop[idn[u]] >= K)
                continue;

            int id(firstInLoop[idn[u]]), posn = (posInComp[id] + K - firstToLoop[idn[u]]) % loopOf[id];
            result[pos] += (getLeftNode(comp[idc[id]][posn]) == lastNode);
        }
    }

    for (int t = 0; t < numQuery; ++t) {
        cout << result[t] << '\n';
        //answer(result[t]);
    }
}

Compilation message

garden.cpp:8: warning: ignoring '#pragma GCC optimization' [-Wunknown-pragmas]
    8 | #pragma GCC optimization ("O3")
      | 
garden.cpp:9: warning: ignoring '#pragma GCC optimization' [-Wunknown-pragmas]
    9 | #pragma GCC optimization ("unroll-loops")
      | 
garden.cpp: In function 'void count_routes(int, int, int, int (*)[2], int, int*)':
garden.cpp:82:17: warning: unused variable 'v' [-Wunused-variable]
   82 |             int v(adj[u][it].fi), id(adj[u][it].se);
      |                 ^
# Verdict Execution time Memory Grader output
1 Incorrect 14 ms 25284 KB Output isn't correct
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 14 ms 25284 KB Output isn't correct
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 14 ms 25284 KB Output isn't correct
2 Halted 0 ms 0 KB -