【整體二分】【P3527】 [POI2011]MET-Meteors
阿新 • • 發佈:2019-01-31
break output for solution main () cas emp 覆蓋
Description
有 n 個國家,總共占有一個環,環被分成了 m 段,已知有 k 次流星雨會落在這個環上的一些位置。再給出每個國家目標收集多少流星,對每個國家求出第幾次流星雨後可以滿足這個國家的目標
Input
第一行是 n,m,意義如上
第二行是 m 個數,第 i 個數 a_i 代表國家 a_i 擁有環上的第 i 段
第三行是 n 個數,代表每個國家的目標
第四行是一個整數 k
下面 k 行每行 3 個數字描述一場流星雨,分別為覆蓋區間和區間內每一段都能收到的隕石數目
Output
對每個國家輸出一行代表答案,無解輸出NIE
Hint
1~\leq~n,m~\leq~3~\times~10^5,其他數字 \leq~10^9
Solution
考慮對於每個國家,我們都可以二分答案然後樹狀數組統計,但是復雜度太高,我們考慮將所有的國家放在一起二分
具體的,我們二分區間 [l, r],計算 [l,, mid] 中修改(流星雨)對查詢(國家)的貢獻。然後枚舉在當前區間中的所有國家,如果滿足目標則下放遞歸 [l, mid],否則將需求減去前半部分的貢獻在下放遞歸 (mid, r]。我們發現在遞歸樹上的每一層每個國家都恰好對應一條線段,一共有 O(\log k) 層,每層使用樹狀數組統計貢獻的總復雜度是 O(k~\log m),共有 O(n) 個國家,對應 O(m) 個區域,所以總復雜度 \Theta(k~\log m~\log n)。
Code
#include <cstdio> #include <vector> #ifdef ONLINE_JUDGE #define freopen(a, b, c) #define printtime() #else #include <ctime> #define printtime() printf("Times used = %ld ms\n", clock()) #endif #define ci const int #define cl const long long typedef long long int ll; namespace IPT { const int L = 1000000; char buf[L], *front=buf, *end=buf; char GetChar() { if (front == end) { end = buf + fread(front = buf, 1, L, stdin); if (front == end) return -1; } return *(front++); } } template <typename T> inline void qr(T &x) { char ch = IPT::GetChar(), lst = ' '; while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar(); while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar(); if (lst == '-') x = -x; } template <typename T> inline void ReadDb(T &x) { char ch = IPT::GetChar(), lst = ' '; while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar(); while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar(); if (ch == '.') { ch = IPT::GetChar(); double base = 1; while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar(); } if (lst == '-') x = -x; } namespace OPT { char buf[120]; } template <typename T> inline void qw(T x, const char aft, const bool pt) { if (x < 0) {x = -x, putchar('-');} int top=0; do {OPT::buf[++top] = static_cast<char>(x % 10 + '0');} while (x /= 10); while (top) putchar(OPT::buf[top--]); if (pt) putchar(aft); } const int maxn = 300010; struct Zay { int l, r, v; }; Zay sto[maxn]; struct Info { int p;ll v; }; int n, m, k; int MU[maxn], ans[maxn], len[maxn]; ll tree[maxn]; std::vector<int> CU[maxn]; std::vector<Info> down; inline int lowbit(ci x) {return x & -x;} void divide(ci, ci, std::vector<Info>&); void insert(int, ci); ll query(int); signed main() { freopen("1.in", "r", stdin); qr(n); qr(m); for (int i = 1, a; i <= m; ++i) { a = 0; qr(a); CU[a].push_back(i); ++len[a]; } for (int i = 1; i <= n; ++i) qr(MU[i]); qr(k); for (int i = 1; i <= k; ++i) { qr(sto[i].l); qr(sto[i].r); qr(sto[i].v); } for (int i = 1; i <= n; ++i) down.push_back((Info) {i, MU[i]}); divide(1, k, down); for (int i = 1; i <= n; ++i) if (ans[i]) qw(ans[i], '\n', true); else puts("NIE"); printtime(); } void divide(ci l, ci r, std::vector<Info> &s) { if (!s.size()) return; int mid = (l + r) >> 1; for (int i = l; i <= mid; ++i) { if (sto[i].l <= sto[i].r) { insert(sto[i].l, sto[i].v); insert(sto[i].r + 1, -sto[i].v); } else { insert(sto[i].l, sto[i].v); insert(1, sto[i].v); insert(sto[i].r + 1, -sto[i].v); } } std::vector<Info> ldown, rdown; for (auto &i : s) { ll _tmp = i.v; for (int j = 0; j < len[i.p]; ++j) { if ((i.v -= query(CU[i.p][j])) <= 0) { ldown.push_back((Info){i.p, _tmp}); break; } } printf("QWQ%d %d %d\n", l, r, i.v); if (i.v > 0) rdown.push_back(i); } for (int i = l; i <= mid; ++i) { if (sto[i].l <= sto[i].r) { insert(sto[i].l, -sto[i].v); insert(sto[i].r + 1, sto[i].v); } else { insert(sto[i].l, -sto[i].v); insert(1, -sto[i].v); insert(sto[i].r + 1, sto[i].v); } } if (l == r) { for (auto i : ldown) ans[i.p] = mid; } else { divide(l, mid, ldown); divide(mid + 1, r, rdown); } } void insert(int x, ci v) { while (x <= m) { tree[x] += v; x += lowbit(x); } } ll query(int x) { ll _ret = 0; while (x) { _ret += tree[x]; x -= lowbit(x); } return _ret; }
【整體二分】【P3527】 [POI2011]MET-Meteors