제출 #361321

#제출 시각아이디문제언어결과실행 시간메모리
361321Lam_lai_cuoc_doi도로 건설 사업 (JOI13_construction)C++17
100 / 100
1882 ms95084 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;

const bool typetest = 0;
const int N = 2e5 + 5;
struct Edge
{
    int u, v;
    ll w;
    Edge(const int &u = 0, const int &v = 0, const ll &w = 0) : u(u), v(v), w(w)
    {
    }
    bool operator<(const Edge &a) const
    {
        return w < a.w;
    }
};
struct FenwickTree
{
    vector<ll> a;
    int n;
    FenwickTree(const int &n = 0)
    {
        a.resize(n + 1);
        this->n = n;
    }
    void Clear()
    {
        fill(a.begin(), a.end(), 0);
    }
    void Update(int p, int v)
    {
        for (; p <= n; p += p & -p)
            a[p] += v;
    }
    ll Get(int p)
    {
        ll ans(0);
        for (; p > 0; p -= p & -p)
            ans += a[p];
        return ans;
    }
    ll Get(int l, int r)
    {
        return Get(r) - Get(l - 1);
    }
};
struct RangeFen
{
    FenwickTree s1, s2;
    int n;
    RangeFen(const int &n = 0)
    {
        this->n = n;
        s1 = FenwickTree(n);
        s2 = FenwickTree(n);
    }
    void Clear()
    {
        s1.Clear();
        s2.Clear();
    }
    void Update(int l, int r, ll v)
    {
        s1.Update(l, v);
        s1.Update(r + 1, -v);
        s2.Update(l, (l - 1) * v);
        s2.Update(r + 1, -v * r);
    }
    ll Get(int p)
    {
        return s1.Get(p) * p - s2.Get(p);
    }
    ll Get(int l, int r)
    {
        return Get(r) - Get(l - 1);
    }
} f;
struct dsu
{
    int par[N];
    dsu()
    {
        memset(par, -1, sizeof par);
    }
    int findpar(int v)
    {
        return par[v] < 0 ? v : par[v] = findpar(par[v]);
    }
    bool merge(int u, int v)
    {
        u = findpar(u);
        v = findpar(v);
        if (u == v)
            return false;
        if (par[u] < par[v])
            swap(u, v);
        par[v] += par[u];
        par[u] = v;
        return true;
    }
} g;
int n, m, c;
int u[N], v[N], p[N], q[N], r[N], s[N];
vector<int> x, y;
vector<ll> ans, res;
vector<vector<int>> pos;
vector<vector<pair<int, int>>> in, out;
vector<Edge> e;

void Read()
{
    cin >> n >> m >> c;
    x.reserve(m * 2 + n);
    y.reserve(m * 2 + n);
    for (int i = 1; i <= n; ++i)
    {
        cin >> u[i] >> v[i];
        x.push_back(u[i]);
        y.push_back(v[i]);
    }
    for (int i = 1; i <= m; ++i)
    {
        cin >> p[i] >> q[i] >> r[i] >> s[i];
        x.push_back(p[i]);
        x.push_back(r[i]);
        y.push_back(q[i]);
        y.push_back(s[i]);
    }
}

void Sort(vector<int> &s)
{
    sort(s.begin(), s.end());
    s.resize(unique(s.begin(), s.end()) - s.begin());
}

int Find(vector<int> &s, int v)
{
    return lower_bound(s.begin(), s.end(), v) - s.begin();
}

void Sort_pos()
{
    for (int i = 0; i < (int)pos.size(); ++i)
        sort(pos[i].begin(), pos[i].end(), [&](const int &x, const int &y) {
            return v[x] < v[y];
        });
}

void Prog(int sz, vector<int> &y)
{
    for (int i = 0; i < (int)sz; ++i)
    {
        for (auto j : in[i])
            f.Update(Find(y, j.first) + 1, Find(y, j.second), 1);
        for (int j = 0; j < (int)pos[i].size(); ++j)
        {
            int t = j + 1;
            while (t < (int)pos[i].size() && f.Get(Find(y, v[pos[i][j]]) + 1, Find(y, v[pos[i][t]])) == 0)
            {
                e.emplace_back(pos[i][t], pos[i][t - 1], v[pos[i][t]] - v[pos[i][t - 1]]);
                ++t;
            }
            j = t - 1;
        }
        for (auto j : out[i])
            f.Update(Find(y, j.first) + 1, Find(y, j.second), -1);
    }
}

void Kruskal()
{
    sort(e.begin(), e.end());
    ans.reserve((int)e.size() + 1);
    ans.push_back(0);
    for (auto i : e)
        if (g.merge(i.u, i.v)){
            ans.push_back(i.w);
        }
    res.resize(ans.size(), 0);
    for (int i = 1; i < (int)ans.size(); ++i)
        res[i] = res[i - 1] + ans[i];
}

void Solve()
{
    Sort(x);
    Sort(y);
    f = RangeFen((int)max(x.size(), y.size()));
    pos.resize(max(x.size(), y.size()));
    in.resize(max(x.size(), y.size()));
    out.resize(max(x.size(), y.size()));
    for (int i = 1; i <= n; ++i)
        pos[Find(x, u[i])].push_back(i);
    Sort_pos();
    for (int i = 1; i <= m; ++i)
    {
        in[Find(x, p[i])].push_back({q[i], s[i]});
        out[Find(x, r[i])].push_back({q[i], s[i]});
    }
    Prog(x.size(), y);
    for (int i = 0; i < (int)x.size(); ++i)
    {
        pos[i].clear();
        in[i].clear();
        out[i].clear();
    }
    for (int i = 1; i <= n; ++i)
    {
        pos[Find(y, v[i])].push_back(i);
        swap(u[i], v[i]);
    }
    Sort_pos();
    for (int i = 1; i <= m; ++i)
    {
        in[Find(y, q[i])].push_back({p[i], r[i]});
        out[Find(y, s[i])].push_back({p[i], r[i]});
    }
    Prog(y.size(), x);
    Kruskal();
    while (c--)
    {
        int k;
        ll b;
        cin >> b >> k;
        if (k < n - (int)ans.size() + 1)
        {
            cout << "-1\n";
            continue;
        }
        k -= n - ans.size() + 1;
        int j = max((int)(lower_bound(ans.begin() + 1, ans.end(), b) - ans.begin()), (int)ans.size() - k);
        cout << res[j - 1] + b * (ans.size() - j) + (n - ans.size() + 1) * b << "\n";
    }
}

int32_t main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t(1);
    if (typetest)
        cin >> t;
    for (int _ = 1; _ <= t; ++_)
    {
        Read();
        Solve();
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...