1. 程式人生 > >【整體二分】【P3527】 [POI2011]MET-Meteors

【整體二分】【P3527】 [POI2011]MET-Meteors

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