Submission #361259

#TimeUsernameProblemLanguageResultExecution timeMemory
361259RyoPham도로 건설 사업 (JOI13_construction)C++14
100 / 100
2070 ms209992 KiB
#define taskname "test"

#include <bits/stdc++.h>

using namespace std;

#define sz(x) (int)x.size()
#define fi first
#define se second

typedef long long lli;
typedef pair<int, int> pii;

const int maxn = 6e5 + 5;

int n, m, Q;
int x[maxn], y[maxn];
int xl[maxn], yl[maxn], xr[maxn], yr[maxn];

int qB[maxn], qH[maxn];

vector<int> ox, oy;

vector<pii> posX[maxn], posY[maxn];
vector<pii> queryYY_x[maxn], queryXX_y[maxn];

vector<pii> addX[maxn], delX[maxn];
vector<pii> addY[maxn], delY[maxn];

vector<pair<int, pii>> edges;

struct segment_tree
{
    int max_val[maxn * 4], lazy[maxn * 4];

    void init()
    {
        fill(begin(max_val), end(max_val), 0);
        fill(begin(lazy), end(lazy), 0);
    }

    void push(int x)
    {
        if(lazy[x] == 0) return;
        int t = lazy[x];

        for(int i = x * 2; i <= x * 2 + 1; ++i)
        {
            lazy[i] += t;
            max_val[i] += t;
        }

        lazy[x] = 0;
    }

    void update(int x, int l, int r, int L, int R, int k)
    {
        if(L > r || l > R) return;
        if(l >= L && r <= R)
        {
            max_val[x] += k;
            lazy[x] += k;
            return;
        }
        push(x);
        int mid = (l + r) / 2;
        update(x * 2, l, mid, L, R, k);
        update(x * 2 + 1, mid + 1, r, L, R, k);
        max_val[x] = max(max_val[x * 2], max_val[x * 2 + 1]);
    }

    int get(int x, int l, int r, int L, int R)
    {
        if(L > r || l > R) return 0;
        if(l >= L && r <= R)
            return max_val[x];
        push(x);
        int mid = (l + r) / 2;
        return max(get(x * 2, l, mid, L, R),
                   get(x * 2 + 1, mid + 1, r, L, R));
    }
} tree;

void read_input()
{
    cin >> n >> m >> Q;
    for(int i = 1; i <= n; ++i)
        cin >> x[i] >> y[i];
    for(int i = 1; i <= m; ++i)
        cin >> xl[i] >> yl[i] >> xr[i] >> yr[i];
    for(int i = 1; i <= Q; ++i)
        cin >> qB[i] >> qH[i];
}

int lwb(const vector<int>&arr, int k)
{
    return lower_bound(arr.begin(), arr.end(), k) - arr.begin() + 1;
}

void init()
{
    /// compress
    for(int i = 1; i <= n; ++i)
    {
        ox.push_back(x[i]);
        oy.push_back(y[i]);
    }
    for(int i = 1; i <= m; ++i)
    {
        ox.push_back(xl[i]);
        ox.push_back(xr[i]);
        oy.push_back(yl[i]);
        oy.push_back(yr[i]);
    }
    sort(ox.begin(), ox.end());
    ox.erase(unique(ox.begin(), ox.end()), ox.end());
    sort(oy.begin(), oy.end());
    oy.erase(unique(oy.begin(), oy.end()), oy.end());
    for(int i = 1; i <= n; ++i)
    {
        x[i] = lwb(ox, x[i]);
        y[i] = lwb(oy, y[i]);
        posX[y[i]].push_back(pii(x[i], i));
        posY[x[i]].push_back(pii(y[i], i));
    }
    for(int i = 1; i <= m; ++i)
    {
        xl[i] = lwb(ox, xl[i]);
        xr[i] = lwb(ox, xr[i]);
        yl[i] = lwb(oy, yl[i]);
        yr[i] = lwb(oy, yr[i]);
    }

    /// make queries
    for(int x = 1; x <= sz(ox); ++x)
    {
        sort(posY[x].begin(), posY[x].end());
        for(int i = 1; i < sz(posY[x]); ++i)
            queryYY_x[x].push_back(pii(posY[x][i - 1].se, posY[x][i].se));
    }
    for(int y = 1; y <= sz(oy); ++y)
    {
        sort(posX[y].begin(), posX[y].end());
        for(int i = 1; i < sz(posX[y]); ++i)
            queryXX_y[y].push_back(pii(posX[y][i - 1].se, posX[y][i].se));
    }
    for(int i = 1; i <= m; ++i)
    {
        addX[xl[i]].push_back(pii(yl[i], yr[i]));
        delX[xr[i]].push_back(pii(yl[i], yr[i]));

        addY[yl[i]].push_back(pii(xl[i], xr[i]));
        delY[yr[i]].push_back(pii(xl[i], xr[i]));
    }


    /// solve all queries
    tree.init();
    for(int x = 1; x <= sz(ox); ++x)
    {
        for(auto&to: addX[x])
            tree.update(1, 1, sz(oy), to.fi, to.se, 1);
        for(auto&to: queryYY_x[x])
        {
            int i = to.fi, j = to.se;
            int l = y[i], r = y[j];
            if(tree.get(1, 1, sz(oy), l, r) > 0) continue;
            edges.push_back(make_pair(oy[y[j] - 1] - oy[y[i] - 1], pii(i, j)));
        }
        for(auto&to: delX[x])
            tree.update(1, 1, sz(oy), to.fi, to.se, -1);
    }
    tree.init();
    for(int y = 1; y <= sz(oy); ++y)
    {
        for(auto&to: addY[y])
            tree.update(1, 1, sz(ox), to.fi, to.se, 1);
        for(auto&to: queryXX_y[y])
        {
            int i = to.fi, j = to.se;
            int l = x[i], r = x[j];
            if(tree.get(1, 1, sz(ox), l, r) > 0) continue;
            edges.push_back(make_pair(ox[x[j] - 1] - ox[x[i] - 1], pii(i, j)));
        }
        for(auto&to: delY[y])
            tree.update(1, 1, sz(ox), to.fi, to.se, -1);
    }
}

int lab[maxn];
int cnt = 0;
int arr[maxn];

int find_set(int u)
{
    return lab[u] < 0 ? u : lab[u] = find_set(lab[u]);
}

bool union_sets(int u, int v)
{
    u = find_set(u); v = find_set(v);
    if(u == v) return false;
    if(lab[u] < lab[v]) swap(u, v);
    lab[v] += lab[u];
    lab[u] = v;
    return true;
}

lli pref[maxn];

void solve()
{
    sort(edges.begin(), edges.end());
    //for(auto&to: edges) cerr << to.fi << ' ' << to.se.fi << ' ' << to.se.se << '\n';
    fill(lab + 1, lab + n + 1, -1);
    int ncc = n;
    for(auto&e: edges)
    {
        int w = e.fi;
        int u = e.se.fi, v = e.se.se;
        if(union_sets(u, v))
        {
            arr[++cnt] = w;
            --ncc;
        }
    }

    reverse(arr + 1, arr + cnt + 1);
    pref[0] = 0;
    for(int i = 1; i <= cnt; ++i)
        pref[i] = pref[i - 1] + arr[i];

    for(int i = 1; i <= Q; ++i)
    {
        int B = qB[i], H = qH[i];
        if(H < ncc)
        {
            cout << "-1\n";
            continue;
        }
        H -= ncc;
        int low = 1, high = min(cnt, H);
        while(low <= high)
        {
            int mid = (low + high) / 2;
            if(arr[mid] > B)
                low = mid + 1;
            else high = mid - 1;
        }
        cout << pref[cnt] - pref[high] + B * 1LL * (high + ncc) << '\n';
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    read_input();
    init();
    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...