1. 程式人生 > 其它 >Loj #6284. 數列分塊入門 8

Loj #6284. 數列分塊入門 8

Description

Loj傳送門

Solution

個人認為是 \(Loj\) 上這幾道分塊題中比較好的一道題。

對於這道題,我們對於每一塊打一個 \(lazy\) 標記,表示當前塊是否被完整賦過值,即全部賦值為 \(c\)

修改時,整塊的直接修改 \(lazy\) 標記,兩頭多餘的部分暴力修改原陣列。

注意: 整個塊都要重新賦值一遍。

  • 在查詢範圍內的:賦值為 \(c\)

  • 在查詢範圍外的:賦值為 \(lazy\) 標記。

然後把該塊的 \(lazy\) 標記賦值為 \(INF\)

查詢時,整塊的直接判斷求和,並把 \(lazy\) 改為 \(c\);兩頭的暴力列舉判斷,同時在有 \(lazy\)

標記時進行上述修改。

修改的部分我對著資料調了好久 \(QwQ\)

經驗:一定要想好了在寫,不然會漏掉許多細節。

具體見程式碼吧。

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <cmath>
#define INF 1e18
#define ll long long
#define ri register int

using namespace std;

inline ll read(){
	ll x = 0, f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
	return x * f;
}

const ll N = 1e5 + 10;
ll n, B, tot;
ll a[N], be[N], ml[N], mr[N], lazy[N];

inline void build(){
	B = sqrt(n);
	tot = n / B + (B * B != n);
	for(ri i = 1; i <= n; i++)
		be[i] = (i - 1) / B + 1;
	for(ri i = 1; i <= tot; i++){
		lazy[i] = INF;
		ml[i] = (i - 1) * B + 1;
		mr[i] = i * B;
	}
	mr[tot] = n;
}

inline ll calc(int l, int r, int c){
	ll res = 0;
	if(lazy[be[l]] == INF){
		for(ri i = l; i <= r; i++)
			res += (a[i] == c), a[i] = c;
	}else{
		if(lazy[be[l]] == c) res += (r - l + 1);
		else{
			for(int i = l; i <= r; i++) a[i] = c;
			for(int i = ml[be[l]]; i < l; i++) a[i] = lazy[be[l]];
			for(int i = r + 1; i <= mr[be[l]]; i++) a[i] = lazy[be[l]];
			lazy[be[l]] = INF;
		}
	}
	return res;
}

inline ll solve(ll l, ll r, ll c){
	if(be[l] == be[r]) return calc(l, r, c);
	ll res = 0;
	for(ll i = be[l] + 1; i <= be[r] - 1; i++){
		if(lazy[i] == INF){
			for(ri j = ml[i]; j <= mr[i]; j++)
				res += (a[j] == c);
		}else if(lazy[i] == c) res += B;
		lazy[i] = c;
	}
	res += calc(l, mr[be[l]], c) + calc(ml[be[r]], r, c);
	return res;
}

signed main(){
	freopen("#6284.in", "r", stdin);
	freopen("#6284.out", "w", stdout);
	n = read();
	for(ri i = 1; i <= n; i++)
		a[i] = read();
	build();
	for(ri i = 1; i <= n; i++){
		ri l = read(), r = read(), c = read();
		printf("%lld\n", solve(l, r, c));
	}
	return 0;
}

End

本文來自部落格園,作者:{xixike},轉載請註明原文連結:https://www.cnblogs.com/xixike/p/15388008.html