Submission #105572

#TimeUsernameProblemLanguageResultExecution timeMemory
105572jwvg0425도로 건설 사업 (JOI13_construction)C++17
100 / 100
2655 ms167324 KiB
#include <stdio.h> #include <vector> #include <queue> #include <algorithm> #include <iostream> #include <string> #include <bitset> #include <map> #include <set> #include <tuple> #include <string.h> #include <math.h> #include <random> #include <functional> #include <assert.h> #include <math.h> #define all(x) (x).begin(), (x).end() #define xx first #define yy second using namespace std; using i64 = long long int; using ii = pair<int, int>; using ii64 = pair<i64, i64>; class Mapping { public: void init(const vector<i64>& raw, int base = 0) { start = base; arr = raw; sort(arr.begin(), arr.end()); arr.erase(unique(arr.begin(), arr.end()), arr.end()); } int get_idx(i64 k) { return start + (lower_bound(all(arr), k) - arr.begin()); } i64 get_value(int idx) { return arr[idx - start]; } int size() { return arr.size(); } private: int start; vector<i64> arr; }; class FenwickTree { public: FenwickTree(int k) { data.resize(k); } i64 sum(int n) { i64 ans = 0; while (n > 0) { ans += data[n]; n -= (n & -n); } return ans; } void add(int n, i64 num) { while (n < data.size()) { data[n] += num; n += (n & -n); } } private: vector<i64> data; }; struct Edge { Edge() = default; Edge(int start, int end, int cost) : s(start), e(end), c(cost) {} int s, e, c; }; vector<Edge> edges; int parent[200005]; int find(int x) { if (parent[x] == x) return x; return parent[x] = find(parent[x]); } void merge(int x, int y) { x = find(x); y = find(y); parent[x] = y; } struct Events { //l ~ r 영역(l에 +1, r에 -1) vector<ii> area; // xpos, idx vector<ii> pos; }; void buildGraph(Mapping& mapping, vector<Events>& events) { FenwickTree cover(mapping.size() + 3); FenwickTree points(mapping.size() + 3); for (auto& es : events) { sort(all(es.pos)); for (auto& area : es.area) { cover.add(area.xx, 1); cover.add(area.yy, -1); if (area.xx < area.yy) points.add(area.xx, 1); else points.add(area.yy, -1); } if (es.pos.empty()) continue; for (int i = 0; i < es.pos.size() - 1; i++) { int sx = mapping.get_idx(es.pos[i].xx); int ex = mapping.get_idx(es.pos[i + 1].xx); if (cover.sum(sx) > 0 || cover.sum(ex) > 0) continue; if (points.sum(ex) - points.sum(sx - 1) > 0) continue; edges.emplace_back(es.pos[i].yy, es.pos[i + 1].yy, es.pos[i + 1].xx - es.pos[i].xx); } } } int main() { int n, m, c; scanf("%d %d %d", &n, &m, &c); vector<ii> towns(n + 1); vector<ii> st(m), ed(m); vector<i64> xpos, ypos; for (int i = 1; i <= n; i++) { scanf("%d %d", &towns[i].xx, &towns[i].yy); xpos.push_back(towns[i].xx); ypos.push_back(towns[i].yy); } for (int i = 0; i < m; i++) { scanf("%d %d %d %d", &st[i].xx, &st[i].yy, &ed[i].xx, &ed[i].yy); xpos.push_back(st[i].xx); xpos.push_back(ed[i].xx); xpos.push_back(ed[i].xx + 1); ypos.push_back(st[i].yy); ypos.push_back(ed[i].yy); ypos.push_back(ed[i].yy + 1); } Mapping xMapping; Mapping yMapping; xMapping.init(xpos, 1); yMapping.init(ypos, 1); // y 좌표, (해당 y에서 event) vector<Events> xEvents(yMapping.size() + 3); vector<Events> yEvents(xMapping.size() + 3); for (int i = 1; i <= n; i++) { xEvents[yMapping.get_idx(towns[i].yy)].pos.emplace_back(towns[i].xx, i); yEvents[xMapping.get_idx(towns[i].xx)].pos.emplace_back(towns[i].yy, i); } for (int i = 0; i < m; i++) { st[i].yy = yMapping.get_idx(st[i].yy); ed[i].yy = yMapping.get_idx(ed[i].yy); st[i].xx = xMapping.get_idx(st[i].xx); ed[i].xx = xMapping.get_idx(ed[i].xx); xEvents[st[i].yy].area.emplace_back(st[i].xx, ed[i].xx + 1); xEvents[ed[i].yy + 1].area.emplace_back(ed[i].xx + 1, st[i].xx); yEvents[st[i].xx].area.emplace_back(st[i].yy, ed[i].yy + 1); yEvents[ed[i].xx + 1].area.emplace_back(ed[i].yy + 1, st[i].yy); } buildGraph(xMapping, xEvents); buildGraph(yMapping, yEvents); sort(all(edges), [](const Edge& l, const Edge& r) { return l.c < r.c; }); vector<int> used; for (int i = 1; i <= n; i++) parent[i] = i; for (auto& e : edges) { if (find(e.s) == find(e.e)) continue; merge(e.s, e.e); used.push_back(e.c); } int minNeed = 0; for (int i = 1; i <= n; i++) { if (find(i) != i) continue; minNeed++; } used.push_back(0); // sentry sort(all(used)); vector<i64> usedSum(used.size()); for (int i = 1; i < used.size(); i++) usedSum[i] = usedSum[i - 1] + used[i]; for (int i = 0; i < c; i++) { i64 b, h; scanf("%lld %lld", &b, &h); if (h < minNeed) { printf("-1\n"); continue; } // 이분 탐색으로, 코스트가 b이상인 맨 왼쪽 간선 찾는다. // b이상인것 전부 제외하면 됨 int ignore = lower_bound(all(used), b) - used.begin(); int setup = used.size() - ignore; int setupMax = h - minNeed; setup = min(setup, setupMax); ignore = used.size() - setup; i64 total = usedSum[ignore - 1] + (minNeed + setup) * b; printf("%lld\n", total); } return 0; }

Compilation message (stderr)

construction.cpp: In member function 'void FenwickTree::add(int, i64)':
construction.cpp:82:12: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   while (n < data.size())
          ~~^~~~~~~~~~~~~
construction.cpp: In function 'void buildGraph(Mapping&, std::vector<Events>&)':
construction.cpp:154:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (int i = 0; i < es.pos.size() - 1; i++)
                   ~~^~~~~~~~~~~~~~~~~~~
construction.cpp: In function 'int main()':
construction.cpp:265:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 1; i < used.size(); i++)
                  ~~^~~~~~~~~~~~~
construction.cpp:174:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d %d %d", &n, &m, &c);
  ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
construction.cpp:182:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d %d", &towns[i].xx, &towns[i].yy);
   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
construction.cpp:189:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d %d %d %d", &st[i].xx, &st[i].yy, &ed[i].xx, &ed[i].yy);
   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
construction.cpp:271:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%lld %lld", &b, &h);
   ~~~~~^~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...