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


    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~ imes~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
    ", 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], '
    ', 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
    ", 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;
    }
  • 相关阅读:
    Naive Operations HDU6315 (杭电多校2G)
    Baker Vai LightOJ
    LOJ#6278. 数列分块入门 2
    LOJ#6277. 数列分块入门 1
    Picture POJ
    Who Gets the Most Candies? POJ
    Dividing the Path POJ
    Balanced Sequence HDU
    归并排序
    Flying to the Mars
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/10343170.html
Copyright © 2020-2023  润新知