loj数列分块入门

Posted PushyTao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj数列分块入门相关的知识,希望对你有一定的参考价值。

入门 1-区间加法-单点查询

ll n,a[maxn],lazy[maxn];
int main() {
	n = read;
	for(int i=1; i<=n; i++) a[i] = read;
	int blk = sqrt(n);
	for(int ii=1; ii<=n; ii++) {
		int op = read,l = read,r = read,c = read;
		if( op == 0) {
			for(int i=l; i<min(r+1,(l/blk+1)*blk); i++) {
				a[i] += c;
			}
			for(int i=l/blk+1; i<r/blk; i++) {
				lazy[i] += c;
			}
			if(l / blk != r / blk) {
				for(int i=r/blk*blk; i<=r; i++) a[i] += c;
			}
		} else {
			printf("%lld\\n",a[r] + lazy[r/blk]);
		}
	}
	return 0;
}
/**
4
1 2 2 3
0 1 3 1
1 0 1 0
0 1 2 2
1 0 2 0

2
5
**/

入门 2-区间加法-区间查询

const int maxn = 1e5 + 7;
ll n, a[maxn];
vector<ll> vet[maxn];
ll blk, lazy[maxn], b[maxn];
void reget(int id) {
    vet[id].clear();

    for (int i = (id - 1) * blk + 1; i <= min(n, id * blk); i++) {
        vet[id].push_back(a[i]);
    }

    sort(vet[id].begin(), vet[id].end());
}
void update(ll l, ll r, ll c) {
    for (int i = l; i <= min(b[l]*blk, r); i++)
        a[i] += c;

    reget(b[l]);

    if (b[l] != b[r]) {
        for (int i = (b[r] - 1) * blk + 1; i <= r; i++)
            a[i] += c;

        reget(b[r]);
    }

    for (int i = b[l] + 1; i <= b[r] - 1; i++) {
        lazy[i] += c;
    }
}
ll query(ll l, ll r, ll val) {
    ll ret = 0;

    for (int i = l; i <= min(b[l]*blk, r); i++) {
        if (a[i] + lazy[b[l]] < val)
            ++ ret;
    }

    if (b[l] != b[r]) {
        for (int i = (b[r] - 1) * blk + 1; i <= r; i++) {
            if (a[i] + lazy[b[r]] < val)
                ++ ret;
        }
    }

    for (int i = b[l] + 1; i <= b[r] - 1; i++) {
        int get = val - lazy[i];
        //      ret += upper_bound(vet[i].begin(),vet[i].end(),get) - lower_bound(vet[i].begin(),vet[i].end(),get);
        ret += lower_bound(vet[i].begin(), vet[i].end(), get) - vet[i].begin();
    }

    return ret;
}
int main() {
    n = read;

    for (int i = 1; i <= n; i++)
        a[i] = read;

    blk = sqrt(n);

    for (int i = 1; i <= n; i++) {
        b[i] = (i - 1) / blk + 1;
        vet[b[i]].push_back(a[i]);
    }

    for (int i = 1; i <= b[n]; i++)
        sort(vet[i].begin(), vet[i].end());

    for (int i = 1; i <= n; i++) {
        int op = read, l = read, r = read, c = read;

        if (op == 0)
            update(l, r, c);
        else
            printf("%lld\\n", query(l, r, c * c));
    }

    return 0;
}
/**
4
1 2 2 3
0 1 3 1
1 1 3 2
1 1 4 1
1 2 3 2

3
0
2
**/

入门 3-区间加法-单点查询

const int maxn = 1e5 + 7;
ll n, a[maxn];
vector<ll> vet[maxn];
ll blk, lazy[maxn], b[maxn];
void reget(int id) {
    vet[id].clear();

    for (int i = (id - 1) * blk + 1; i <= min(n, id * blk); i++) {
        vet[id].push_back(a[i]);
    }

    sort(vet[id].begin(), vet[id].end());
}
void update(ll l, ll r, ll c) {
    for (int i = l; i <= min(b[l]*blk, r); i++)
        a[i] += c;

    reget(b[l]);

    if (b[l] != b[r]) {
        for (int i = (b[r] - 1) * blk + 1; i <= r; i++)
            a[i] += c;

        reget(b[r]);
    }

    for (int i = b[l] + 1; i <= b[r] - 1; i++) {
        lazy[i] += c;
    }
}
ll query(ll l, ll r, ll val) {
    ll ret = -1;

    for (int i = l; i <= min(b[l]*blk, r); i++) {
        if (a[i] + lazy[b[l]] < val)
            ret = max(ret, a[i] + lazy[b[l]]);
    }

    if (b[l] != b[r]) {
        for (int i = (b[r] - 1) * blk + 1; i <= r; i++) {
            if (a[i] + lazy[b[r]] < val)
                ret = max(ret, a[i] + lazy[b[r]]);
        }
    }

    for (int i = b[l] + 1; i <= b[r] - 1; i++) {
        ll get = val - lazy[i];
        vector<ll>::iterator l = lower_bound(vet[i].begin(), vet[i].end(), get);

        if (l == vet[i].begin())
            continue;

        l --;
        ret = max(ret, *l + lazy[i]);
    }

    return ret;
}
int main() {
    n = read;

    for (int i = 1; i <= n; i++)
        a[i] = read;

    blk = sqrt(n);

    for (int i = 1; i <= n; i++) {
        b[i] = (i - 1) / blk + 1;
        vet[b[i]].push_back(a[i]);
    }

    for (int i = 1; i <= b[n]; i++)
        sort(vet[i].begin(), vet[i].end());

    for (int i = 1; i <= n; i++) {
        int op = read, l = read, r = read, c = read;

        if (op == 0)
            update(l, r, c);
        else
            printf("%lld\\n", query(l, r, c));

        //      debug(i);
    }

    return 0;
}
/**
4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4

3
-1
**/

入门 4-区间加法-区间查询

ll n,a[maxn];
ll blk,lazy[maxn],b[maxn],sum[maxn];
void update(ll l,ll r,ll c) {
	for(int i=l; i<=min(b[l]*blk,r); i++) a[i] += c,sum[b[l]] += c;
	if(b[l] != b[r]) {
		for(int i=(b[r] - 1) * blk+1; i<=r; i++) a[i] += c,sum[b[r]] += c;
	}
	for(int i=b[l]+1; i<=b[r] - 1; i++) {
		lazy[i] += c;
	}
}
ll query(ll l,ll r,ll val) {
	ll ret = 0;
	for(int i=l; i<=min(b[l]*blk,r); i++) {
		ret += a[i] + lazy[b[l]];
		ret %= (val + 1);
	}
	if(b[l] != b[r]) {
		for(int i=(b[r]-1)*blk+1; i<=r; i++) {
			ret += a[i] + lazy[b[r]];
			ret %= (val + 1);
		}
	}
	for(int i=b[l]+1; i<=b[r]-1; i++) {
		ll add = lazy[i] * blk % (val + 1);
		ret += (sum[i] + add) % (val + 1);
		ret %= (val + 1);
	}
	return ret;
}
int main() {
	n = read;
	for(int i=1; i<=n; i++) a[i] = read;
	blk = sqrt(n);
	for(int i=1; i<=n; i++) {
		b[i] = (i - 1) / blk + 1;
		sum[b[i]] += a[i];
	}
	for(int i=1; i<=n; i++) {
		int op = read,l = read,r = read,c = read;
		if(op == 0) update(l,r,c);
		else printf("%lld\\n",query(l,r,c));
	}
	return 0;
}
/**
4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4

1
4
**/

入门 5-区间开方-区间查询

ll n,a[maxn];
ll blk,lazy[maxn],b[maxn],sum[maxn];
bool vis[maxnLoj 6282. 数列分块入门 6

Loj 6280 数列分块入门 4

Loj 6281. 数列分块入门 5

Loj 6283. 数列分块入门 7

loj数列分块入门

LOJ6277~6285 数列分块入门