• LOJ #6279. 数列分块入门 3


    LOJ #6279. 数列分块入门 3

    思路&&代码

    区间修改+询问前驱

    (hzwer)大佬说这里的前驱是指严格小于当前值的最大的值

    先分块,分成(sqrt{n})个块,分的时候,每个块用一个(set)来维护块内的值

    区间修改的时候不足一个块的把(set)中的原数删掉,然后加上(c),再放进去,一整个块的直接让增量标记加(c)

    询问前驱的时候符合要求的才算进答案

    关于(lower\_bound)那个地方怎么理解……

    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e5 + 11;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for ( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    vector <int> v[500];
    
    int n, m, a[A], L[A], R[A], add[A], pos[A];
    
    void reset(int x) {
    	v[x].clear();
    	for(int i = L[x]; i <= R[x]; i++) v[x].push_back(a[i]);
    	sort(v[x].begin(), v[x].end());
    }
    
    void change(int l, int r, int c) {
    	int p = pos[l], q = pos[r];
    	if(p == q) {
    		for(int i = l; i <= r; i++) a[i] += c;
    		reset(p); return;
    	}
    	for(int i = l; i <= R[p]; i++) a[i] += c; reset(p);
    	for(int i = L[q]; i <= r; i++) a[i] += c; reset(q);
    	for(int i = p + 1; i < q; i++) add[i] += c;
    	
    }
    
    int ask(int l, int r, int c, int ans = 0) {
    	int p = pos[l], q = pos[r];
    	if(p == q) {
    		for(int i = l; i <= r; i++) if(a[i] + add[p] < c) ans++;
    		return ans;
    	}
    	for(int i = l; i <= R[p]; i++) if(a[i] + add[p] < c) ans++;
    	for(int i = L[q]; i <= r; i++) if(a[i] + add[q] < c) ans++;
    	for(int i = p + 1; i < q; i++) ans += lower_bound(v[i].begin(), v[i].end(), c - add[i]) - v[i].begin();
    	return ans;
    }
    
    int main() {
    	n = read();
    	for(int i = 1; i <= n; i++) a[i] = read();
    	int t = sqrt(n);
    	for(int i = 1; i <= t; i++) {
    		L[i] = sqrt(n) * (i - 1) + 1;
    		R[i] = sqrt(n) * i;
    	}
    	if(R[t] < n) t++, L[t] = R[t - 1] + 1, R[t] = n;
    	for(int i = 1; i <= t; i++) {
    		for(int j = L[i]; j <= R[i]; j++) {
    			pos[j] = i;
    			v[pos[j]].push_back(a[j]);
    		}
    	}
    	for(int i = 1; i <= t; i++) sort(v[i].begin(), v[i].end());
    	m = n;
    	while(m--) {
    		int opt = read(), l = read(), r = read(), c = read();
    		if(opt == 0) change(l, r, c);
    		else cout << ask(l, r, c * c) << '
    ';
    	}
    	return 0;
    }
    
  • 相关阅读:
    hdu 思维风暴
    HDU 4183Pahom on Water(网络流之最大流)
    现在仍在工作的12名最“屌”的程序猿
    安卓ContentObserver模式获取短信用正则自己主动填充验证码
    Android插件实例——360 DroidPlugin具体解释
    mysql---union的使用方法
    SICP 习题 (2.11)解题总结:区间乘法的优化
    jQuery中的ajax
    Ajax的简单总结
    jQuery插件开发
  • 原文地址:https://www.cnblogs.com/loceaner/p/12210422.html
Copyright © 2020-2023  润新知