Submission #677514

#TimeUsernameProblemLanguageResultExecution timeMemory
677514mjhmjh1104방벽 (JOI15_walls)C++17
100 / 100
753 ms28876 KiB
#include <cstdio>
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;

const bool debug = false;

struct Item {
    int a;
    int b;
    int i;
    int fi;
    int se;
    bool operator< (const Item &O) const {
        return b - a < O.b - O.a;
    }
};

pair<long long, long long> operator+ (const pair<long long, long long> &a, const pair<long long, long long> &b) {
    return { a.first + b.first, a.second + b.second };
}

pair<long long, long long> lazy1[524288], lazy2[524288];

void propagate1(int i, int b, int e) {
    if (b != e) {
        lazy1[i * 2 + 1] = lazy1[i * 2 + 1] + lazy1[i];
        lazy1[i * 2 + 2] = lazy1[i * 2 + 2] + lazy1[i];
        lazy1[i] = { 0, 0 };
    }
}

pair<long long, long long> query1(int i, int b, int e, int p) {
    propagate1(i, b, e);
    if (p < b || e < p) return { 0, 0 };
    if (b == e) return lazy1[i];
    int m = (b + e) / 2;
    return query1(i * 2 + 1, b, m, p) + query1(i * 2 + 2, m + 1, e, p);
}

void substitute1(int i, int b, int e, int p, long long v) {
    propagate1(i, b, e);
    if (p < b || e < p) return;
    if (b == e) {
        lazy1[i] = { v, 0 };
        return;
    }
    int m = (b + e) / 2;
    substitute1(i * 2 + 1, b, m, p, v);
    substitute1(i * 2 + 2, m + 1, e, p, v);
}

void update1(int i, int b, int e, int l, int r, long long v1, long long v2) {
    propagate1(i, b, e);
    if (r < l || r < b || e < l) return;
    if (l <= b && e <= r) {
        lazy1[i] = lazy1[i] + make_pair(v1, v2);
        return;
    }
    int m = (b + e) / 2;
    update1(i * 2 + 1, b, m, l, r, v1, v2);
    update1(i * 2 + 2, m + 1, e, l, r, v1, v2);
}

void propagate2(int i, int b, int e) {
    if (b != e) {
        lazy2[i * 2 + 1] = lazy2[i * 2 + 1] + lazy2[i];
        lazy2[i * 2 + 2] = lazy2[i * 2 + 2] + lazy2[i];
    lazy2[i] = { 0, 0 };
    }
}

pair<long long, long long> query2(int i, int b, int e, int p) {
    propagate2(i, b, e);
    if (p < b || e < p) return { 0, 0 };
    if (b == e) return lazy2[i];
    int m = (b + e) / 2;
    return query2(i * 2 + 1, b, m, p) + query2(i * 2 + 2, m + 1, e, p);
}

void substitute2(int i, int b, int e, int p, long long v) {
    propagate2(i, b, e);
    if (p < b || e < p) return;
    if (b == e) {
        lazy2[i] = { v, 0 };
        return;
    }
    int m = (b + e) / 2;
    substitute2(i * 2 + 1, b, m, p, v);
    substitute2(i * 2 + 2, m + 1, e, p, v);
}

void update2(int i, int b, int e, int l, int r, long long v1, long long v2) {
    propagate2(i, b, e);
    if (r < l || r < b || e < l) return;
    if (l <= b && e <= r) {
        lazy2[i] = lazy2[i] + make_pair(v1, v2);
        return;
    }
    int m = (b + e) / 2;
    update2(i * 2 + 1, b, m, l, r, v1, v2);
    update2(i * 2 + 2, m + 1, e, l, r, v1, v2);
}

long long query1(int x, int l) {
    pair<long long, long long> t = query1(0, 0, 262143, x);
    return t.first + t.second * l;
}

long long query2(int x, int l) {
    pair<long long, long long> t = query2(0, 0, 262143, x);
    return t.first + t.second * l;
}

void update1(int p, long long v) {
    substitute1(0, 0, 262143, p, v);
}

void update2(int p, long long v) {
    substitute2(0, 0, 262143, p, v);
}

void update1(int l, int r, long long uA, long long uB) {
    update1(0, 0, 262143, l, r, uA, uB);
}

void update2(int l, int r, long long uA, long long uB) {
    update2(0, 0, 262143, l, r, uA, uB);
}

void update(int l, int r, long long uA, long long uB, int y) {
    if (debug) printf("UPDATE: [%d,%d], %lld, %lld\n", l, r, uA, uB);
    if (y) update2(l, r, uA, uB);
    else update1(l, r, uA, uB);
}

int n, m, p[200006];
vector<Item> v, v1, v2;
long long res[200006];

// stick, x, [l, r]

void sum_left(int s, int x, int l, int r, int y) {
    if (debug) puts("SUM_LEFT");
    if (x <= s) update(l, r, s - x, 0, y);
    else update(l, r, x - s, -1, y);
}

void sum_right(int s, int x, int l, int r, int y) {
    if (debug) puts("SUM_RIGHT");
    if (x >= s) update(l, r, x - s, 0, y);
    else update(l, r, s - x, -1, y);
}

void process(vector<Item> &v, vector<pair<int, pair<int, bool>>> &st, int x, int y) {
    if (debug) puts("PROCESS");
    if (v.empty()) return;
    int n = (int)v.size();
    int a = v[0].a, b = v[0].b;
    if (st.back().second.second) {
        a = st.back().first;
        b = a + (v[0].b - v[0].a);
    } else {
        b = st.back().first;
        a = b - (v[0].b - v[0].a);
    }
    if (a <= x && x <= b) return;
    int l = 0, r = n - 1;
    while (l < r) {
        int m = (l + r + 1) / 2;
        int a, b;
        {
            int L = 0, R = (int)st.size() - 1;
            while (L < R) {
                int M = (L + R + 1) / 2;
                if (st[M].second.first >= m) L = M;
                else R = M - 1;
            }
            if (st[L].second.second) {
                a = st[L].first;
                b = a + (v[m].b - v[m].a);
            } else {
                b = st[L].first;
                a = b - (v[m].b - v[m].a);
            }
        }
        if (a <= x && x <= b) r = m - 1;
        else l = m;
    }
    if (debug) printf("! SIZE=%d\n", (int)st.size());
    int k = (int)st.size() - 1, lt = 0;
    while (k >= 0 && st[k].second.first <= l) {
        if (st[k].second.second) sum_left(st[k].first, x, lt, st[k].second.first, y);
        else sum_right(st[k].first, x, lt, st[k].second.first, y);
        lt = st[k].second.first + 1;
        k--;
        st.pop_back();
    }
    if (k >= 0) {
        if (st[k].second.second) sum_left(st[k].first, x, lt, l, y);
        else sum_right(st[k].first, x, lt, l, y);
    }
    if (x < a) st.push_back({ x, { l, true } });
    else st.push_back({ x, { l, false } });
    if (debug) {
        printf("lt=%d, l=%d\n", lt, l);
        puts("st:");
        for (auto &i: st) printf("%d / %d / %d\n", i.first, i.second.first, i.second.second ? 1 : 0);
    }
}

int main() {
    scanf("%d%d", &n, &m);
    v.resize(n);
    for (int i = 0; i < n; i++) {
        scanf("%d%d", &v[i].a, &v[i].b);
        v[i].i = i;
        v[i].fi = v[i].se = (int)1e9;
    }
    for (int i = 0; i < m; i++) scanf("%d", p + i);

    vector<pair<int, int>> queries1, queries2;
    vector<pair<int, pair<bool, int>>> queries;
    for (int i = 0; i < n; i++) {
        // v[i].a 미만 중 첫번: v[i].fi
        queries1.push_back({ v[i].a, i });
        // v[i].b 초과 중 첫번: v[i].se
        queries2.push_back({ v[i].b, i });
    }
    {
        sort(queries1.rbegin(), queries1.rend());
        int k = 0;
        for (int i = 0; i < m; i++) {
            while (k < (int)queries1.size() && p[i] < queries1[k].first) {
                v[queries1[k].second].fi = i;
                k++;
            }
        }
    }
    {
        sort(queries2.begin(), queries2.end());
        int k = 0;
        for (int i = 0; i < m; i++) {
            while (k < (int)queries2.size() && p[i] > queries2[k].first) {
                v[queries2[k].second].se = i;
                k++;
            }
        }
    }

    sort(v.begin(), v.end());
    for (auto &i: v) {
        if (i.fi < i.se) {
            queries.push_back({ i.fi, { true, (int)v1.size() } });
            v1.push_back(i);
        }
        if (i.fi > i.se) {
            queries.push_back({ i.se, { false, (int)v2.size() } });
            v2.push_back(i);
        }
    }
    sort(queries.begin(), queries.end());
    vector<pair<int, pair<int, bool>>> st1, st2; // pos, idx, stick to left?
    st1.push_back({ (int)1e9, { n - 1, true } });
    st2.push_back({ (int)-1e9, { n - 1, false } });

    if (debug) printf("v1=%d / v2=%d\n", (int)v1.size(), (int)v2.size());

    int k = 0;
    for (int i = 0; i < m; i++) {
        process(v1, st1, p[i], 0);
        process(v2, st2, p[i], 1);
        while (k < (int)queries.size() && queries[k].first <= i) {
            if (queries[k].second.first) update1(queries[k].second.second, v1[queries[k].second.second].a - p[i]);
            else update2(queries[k].second.second, p[i] - v2[queries[k].second.second].b);
            k++;
        }
    }
    for (int i = 0; i < (int)v1.size(); i++) res[v1[i].i] = query1(i, v1[i].b - v1[i].a);
    for (int i = 0; i < (int)v2.size(); i++) res[v2[i].i] = query2(i, v2[i].b - v2[i].a);
    sort(v.begin(), v.end(), [](const Item &a, const Item &b) {
        return a.i < b.i;
    });
    for (int i = 0; i < n; i++) {
        if (debug) printf("\nFI=%d / SE=%d\n", v[i].fi, v[i].se);
        if (v[i].fi == (int)1e9 && v[i].se == (int)1e9) puts("0");
        else printf("%lld\n", res[i]);
    }
}

Compilation message (stderr)

walls.cpp: In function 'int main()':
walls.cpp:214:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  214 |     scanf("%d%d", &n, &m);
      |     ~~~~~^~~~~~~~~~~~~~~~
walls.cpp:217:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  217 |         scanf("%d%d", &v[i].a, &v[i].b);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
walls.cpp:221:38: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  221 |     for (int i = 0; i < m; i++) scanf("%d", p + i);
      |                                 ~~~~~^~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...