Submission #1249196

#TimeUsernameProblemLanguageResultExecution timeMemory
12491961ncogn1toSails (IOI07_sails)C++20
0 / 100
66 ms2632 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; // Segment tree trzymający informację, czy w danym przedziale // jest jakikolwiek delta[i] != 0. Pozwala na: // 1) punktową aktualizację delta[pos] += val // 2) zapytanie: pozycja ostatniego niezerowego elementu <= x // 3) zapytanie: pozycja pierwszego niezerowego elementu >= x struct SegTree { int n; vector<bool> tree; SegTree(int _n): n(_n) { tree.assign(4*n, false); } void update(int idx, int l, int r, int pos, bool has) { if (l == r) { tree[idx] = has; return; } int mid = (l + r) >> 1; if (pos <= mid) update(idx<<1, l, mid, pos, has); else update(idx<<1|1, mid+1, r, pos, has); tree[idx] = tree[idx<<1] | tree[idx<<1|1]; } // public wrapper void update(int pos, bool has) { update(1, 0, n-1, pos, has); } // znajdź ostatnie delta!=0 w [ql..qr], lub -1 jeśli brak int find_last(int idx, int l, int r, int ql, int qr) { if (ql>qr || !tree[idx]) return -1; if (l==r) return l; int mid=(l+r)>>1; int res = -1; if (qr > mid) res = find_last(idx<<1|1, mid+1, r, max(ql,mid+1), qr); if (res != -1) return res; if (ql <= mid) res = find_last(idx<<1, l, mid, ql, min(qr,mid)); return res; } int find_last(int ql, int qr) { return find_last(1,0,n-1, ql, qr); } // znajdź pierwsze delta!=0 w [ql..qr], lub n jeśli brak int find_first(int idx, int l, int r, int ql, int qr) { if (ql>qr || !tree[idx]) return -1; if (l==r) return l; int mid=(l+r)>>1; int res = -1; if (ql <= mid) res = find_first(idx<<1, l, mid, ql, min(qr,mid)); if (res != -1) return res; if (qr > mid) res = find_first(idx<<1|1, mid+1, r, max(ql,mid+1), qr); return res; } int find_first(int ql, int qr) { return find_first(1,0,n-1, ql, qr); } }; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector<pair<int,int>> mast(N); int maxH = 0; for(int i=0;i<N;i++){ cin >> mast[i].first >> mast[i].second; maxH = max(maxH, mast[i].first); } // sortujemy po rosnącej wysokości H sort(mast.begin(), mast.end()); // przygotowujemy delta[0..maxH+1], indeksujemy 1-based int M = maxH + 2; vector<ll> delta(M, 0); SegTree st(M); // funkcja pomocnicza: zmień delta[pos] o val i zaktualizuj drzewo auto apply = [&](int pos, ll val){ delta[pos] += val; st.update(pos, delta[pos] != 0); }; // przetwarzamy kolejne maszty for(auto &p : mast){ int H = p.first; int K = p.second; // dodajemy poziomy do max-widoczności (delta już ma rozmiar M) // teraz musimy dodać +1 na każdym poziomie z przedziału [A..H] int A = H - K + 1; if (A < 1) A = 1; // sprawdzamy, czy A leży wewnątrz grupy zer: bool inGroup = (delta[A] == 0); if (!inGroup) { // prosty przypadek: jedna operacja delta[A]++, delta[H+1]-- apply(A, +1); apply(H+1, -1); } else { // musimy znaleźć granice grupy zer zawierającej A int left_nonzero = st.find_last(0, A-1); int L = (left_nonzero == -1 ? 1 : left_nonzero+1); int right_nonzero = st.find_first(A+1, M-1); int R = (right_nonzero == -1 ? H : right_nonzero-1); // długość prawej części w grupie: segment [A..R] int lenRight = R - A + 1; // będziemy robić dwie aktualizacje: // 1) przedział [L .. L+lenRight-1] +=1 // 2) przedział [R+1 .. H] +=1 int mid1 = L + lenRight - 1; apply(L, +1); apply(mid1+1, -1); if (R+1 <= H) { apply(R+1, +1); apply(H+1, -1); } } } // na koniec budujemy histogram S[L] jako prefix-sum delta vector<ll> S(M,0); for(int i=1;i<=maxH;i++){ S[i] = S[i-1] + delta[i]; } // liczmy niesprawność: suma C(S[L],2) ll result = 0; for(int i=1;i<=maxH;i++){ result += S[i] * (S[i]-1) / 2; } cout << result << "\n"; return 0; }
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...