Submission #1126994

#TimeUsernameProblemLanguageResultExecution timeMemory
1126994whoRigged Roads (NOI19_riggedroads)C++20
100 / 100
278 ms45328 KiB
#include <bits/stdc++.h>

using namespace std;

#define task "palace"
#define etr "\n"
#define ll long long
#define ld long double
#define pii pair<int,int>
#define pli pair<long long,int>
#define pll pair<long long, long long>
#define fi first
#define se second
#define bg begin
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define lwb lower_bound
#define upb upper_bound
#define range(x, l, r) x+l, x+1+r
#define all(x) (x).bg(), (x).end()
#define compact(x) x.resize(unique(all(x)) - (x).bg())
#define sq(x) ((x)*(x))

auto start = chrono::high_resolution_clock::now();

void start_timer()
{
    start = chrono::high_resolution_clock::now();
}

ld elapsed()
{
    auto current = chrono::high_resolution_clock::now();
    ld duration = chrono::duration_cast<chrono::nanoseconds>(current - start).count();
    return duration / 1e9;
}
void freop()
{
    freopen(task".inp", "r", stdin);
    freopen(task".out", "w", stdout);
}

template<class U, class V> istream& operator >> (istream& in, pair<U, V>& p)
{
    in >> p.fi >> p.se;
    return in;
}

template<class U, class V> ostream& operator << (ostream& out, pair<U, V> p)
{
    out << "{" << p.fi << ' ' << p.se << "}";
    return out;
}

template<class T> ostream& operator << (ostream& out, vector<T>& v)
{
    out << "{";
    for (int i=0; i<v.size(); i++)
    {
        out << v[i];
        if (i != v.size() - 1) out << ", ";
    }

    out << "}";
    return out;
}

const int N=3e5, M=1e5, mod=1e9+7;

int n, m;
pii edge[N+5];
int r[N+5];

namespace Sub1
{
    struct DSU
    {
        int connections = 0;
        vector<int> par;

        DSU(int sz) : par(n+5, -1) {}

        int root(int node)
        {
            return par[node] < 0 ? node : par[node] = root(par[node]);
        }

        bool connect(int u, int v)
        {
            u = root(u), v = root(v);

            if (u == v) return false;

            if (-par[u] < -par[v]) swap(u, v);

            connections++;
            par[u] += par[v];
            par[v] = u;

            return true;
        }

        bool same(int u, int v)
        {
            return root(u) == root(v);
        }
    };

    void solve()
    {
        int w[m+5];
        for (int i=1; i<=m; i++) w[i] = i;

        int tmp[m+5];
        bool mark[m+5] = {false};

        for (int i=1; i<n; i++) mark[r[i]] = true;
        do
        {
            DSU dsu(n);
            bool ok = true;
            for (int i=1; i<=m; i++) tmp[w[i]] = i;

            for (int i=1; i<=m; i++)
            {
                if (!dsu.connect(edge[tmp[i]].fi, edge[tmp[i]].se)) continue;
                if (!mark[tmp[i]])
                {
                    ok = false;
                    break;
                }
            }


            if (ok)
            {
                for (int i=1; i<=m; i++) cout << w[i] << ' ';
                return;
            }
        } while (next_permutation(range(w, 1, m)));
    }
}

namespace Sub7
{
    vector<pii> adj[N+5];
    int sub[N+5];
    int timer = 0, a[N+5], in[N+5], out[N+5], head[N+5], p[N+5];
    bool mark[N+5], used[N+5];

    struct SegmentTree
    {
        bool lazy[N*4+5];

        SegmentTree()
        {
            memset(lazy, 0, sizeof(lazy));
        }


        void update(int id, int l, int r, int pos)
        {
            if (pos<l || pos>r) return;
            if (l == r)
            {
                lazy[id] = true;
                return;
            }

            int mid = (l+r) >> 1;

            update(id*2, l, mid, pos);
            update(id*2+1, mid+1, r, pos);

            lazy[id] = lazy[id*2] && lazy[id*2+1];
        }

        int walk(int id, int l, int r, int u, int v)
        {
            if (v<l || u>r || lazy[id]) return 0;
            if (l == r) return l;

            int mid = (l+r) >> 1;
            int res;

            if (res = walk(id*2+1, mid+1, r, u, v)) return res;
            return walk(id*2, l, mid, u, v);
        }
    } seg;

    int edgeID[N+5], edgeToNode[N+5];

    int init(int par, int u)
    {
        sub[u] = 1;
        for (pii p : adj[u])
        {
            int v = p.fi;
            if (v == par) continue;
            edgeID[v] = p.se;
            edgeToNode[p.se] = v;
            sub[u] += init(u, v);
        }

        return sub[u];
    }

    void dfs(int par, int u, int hd)
    {
        head[u] = hd;
        in[u] = ++timer;
        p[u] = par;
        a[in[u]] = u;

        int child = 0;
        for (pii p : adj[u])
        {
            int v = p.fi;
            if (v == par) continue;
            if (sub[v] > sub[child]) child = v;
        }

        if (child) dfs(u, child, hd);

        for (pii p : adj[u])
        {
            int v = p.fi;
            if (v == par || v == child) continue;
            dfs(u, v, v);
        }

        out[u] = timer;
    }

    bool edgeUsed[N+5];
    vector<int> order;

    int hld(int u, int v)
    {
        //cout << u << ' ' << v << ": ";
        int dist = 0;
        vector<int> path;
        while (head[u] != head[v])
        {
            if (in[u] < in[v]) swap(u, v);

            while (true)
            {
                int node = seg.walk(1, 1, n, in[head[u]], in[u]);
                if (node == 0) break;
                //cout << a[node] << ": " << edgeID[a[node]] << "!" << etr;
                dist++;
                seg.update(1, 1, n, node);
                path.pb(edgeID[a[node]]);

            }

            u = p[head[u]];
        }

        if (u == v)
        {
            //cout << dist << etr;
            sort(all(path));

            for (int i : path)
            {
                edgeUsed[i] = true;
                order.pb(i);
            }
            return dist;
        }
        if (in[u] > in[v]) swap(u, v);

        while (true)
        {
            int node = seg.walk(1, 1, n, in[u]+1, in[v]);
            if (node == 0) break;
            //cout << a[node] << ": " << edgeID[a[node]] << "!" << etr;
            dist++;
            seg.update(1, 1, n, node);
            path.pb(edgeID[a[node]]);
        }

        sort(all(path));

        for (int i : path)
        {
            edgeUsed[i] = true;
            order.pb(i);
        }

        //cout << dist << etr;
        return dist;
    }

    int ans[N+5];

    void solve()
    {
        for (int i=1; i<n; i++)
        {
            int u = edge[r[i]].fi, v = edge[r[i]].se;
            adj[u].pb({v, r[i]});
            adj[v].pb({u, r[i]});

            mark[r[i]] = true;
        }

        init(0, 1);
        dfs(0, 1, 1);

        int cur = 1;

        for (int i=1; i<=m; i++)
        {
            if (edgeUsed[i]) continue;
            if (mark[i])
            {
                ans[i] = cur;
                used[ans[i]] = true;
                cur = ans[i] + 1;
                seg.update(1, 1, n, in[edgeToNode[i]]);
                //cout << i << ": " << ans[i] << etr;
                continue;
            }

            ans[i] = cur + hld(edge[i].fi, edge[i].se);
            //cout << i << ": " << ans[i] << etr;
            used[ans[i]] = true;
            cur = ans[i] + 1;
        }

        //cout << order << etr;

        int j = 1;
        for (int i : order)
        {
            while (used[j]) j++;
            ans[i] = j;
            used[j] = true;
        }

        for (int i=1; i<=m; i++) cout << ans[i] << ' ';
    }
};

void process()
{
    cin >> n >> m;
    for (int i=1; i<=m; i++)
    {
        cin >> edge[i];
    }

    for (int i=1; i<n; i++) cin >> r[i];
    sort(range(r, 1, n-1));

    Sub7::solve();
    //if (m <= 9) Sub1::solve();
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    //freop();

    int t=1; //cin >> t;
    while (t--) process();

    return 0;
}

Compilation message (stderr)

riggedroads.cpp: In function 'void freop()':
riggedroads.cpp:41:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   41 |     freopen(task".inp", "r", stdin);
      |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
riggedroads.cpp:42:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   42 |     freopen(task".out", "w", stdout);
      |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...