HDU 4391 Paint The Wall(分块的区间维护)
题意:给出几个操作,把l-r赋值为z,询问l-r有几个z,其中z < INT_MAX
思路:因为z很大,所以很难直接用线段树去维护。这里可以使用分块来解决。我们可以让每个块用map去储存map[i]的个数,用类似线段树的lazy标记来给整个块更新,当需要对块内某些数操作时再pushdown。
注意一下不要随意开辟map的空间,在计算区间的z的个数时应采用
if(b[i].num.find(z) != b[i].num.end()) ans += b[i].num[z];
减少空间开辟。
代码:
#include<set> #include<map> #include<stack> #include<cmath> #include<queue> #include<vector> #include<string> #include<cstdio> #include<cstring> #include<sstream> #include<iostream> #include<algorithm> typedef long long ll; using namespace std; const int maxn = 100000 + 10; const int MOD = 1e9 + 7; const int INF = 0x3f3f3f3f; struct Block{ map<int, int> num; int lazy, L, R; }b[1000]; int belong[maxn], a[maxn], block, sz; int n, m; void init(){ block = sqrt(n * 1.0); for(int i = 0; i < n; i++) belong[i] = i / block + 1; sz = belong[n - 1]; for(int i = 1; i <= sz; i++){ b[i].lazy = -1; b[i].L = (i - 1) * block; b[i].R = min(b[i].L + block - 1, n - 1); b[i].num.clear(); for(int j = b[i].L; j <= b[i].R; j++){ b[i].num[a[j]]++; } } } void push_down(int x){ b[x].num.clear(); for(int i = b[x].L; i <= b[x].R; i++) a[i] = b[x].lazy; b[x].num[b[x].lazy] = b[x].R - b[x].L + 1; b[x].lazy = -1; } void update(int ll, int rr, int z){ int l = belong[ll], r = belong[rr]; int L, R; if(l == r){ if(b[l].lazy != -1) push_down(l); for(int i = ll; i <= rr; i++){ b[l].num[a[i]]--; b[l].num[z]++; a[i] = z; } } else{ L = ll, R = b[l].R; if(b[l].lazy != -1) push_down(l); for(int i = L; i <= R; i++){ b[l].num[a[i]]--; b[l].num[z]++; a[i] = z; } L = l + 1, R = r - 1; for(int i = L; i <= R; i++) b[i].lazy = z; L = b[r].L, R = rr; if(b[r].lazy != -1) push_down(r); for(int i = L; i <= R; i++){ b[r].num[a[i]]--; b[r].num[z]++; a[i] = z; } } } int query(int ll, int rr, int z){ int l = belong[ll], r = belong[rr]; int L, R, ans = 0; if(l == r){ if(b[l].lazy != -1) push_down(l); for(int i = ll; i <= rr; i++){ if(a[i] == z) ans++; } return ans; } else{ L = ll, R = b[l].R; if(b[l].lazy != -1) push_down(l); for(int i = L; i <= R; i++){ if(a[i] == z) ans++; } L = l + 1, R = r - 1; for(int i = L; i <= R; i++){ if(b[i].lazy != -1){ if(b[i].lazy == z) ans += b[i].R - b[i].L + 1; } else{ if(b[i].num.find(z) != b[i].num.end()) ans += b[i].num[z]; //不开辟新空间 } } L = b[r].L, R = rr; if(b[r].lazy != -1) push_down(r); for(int i = L; i <= R; i++){ if(a[i] == z) ans++; } return ans; } } int main(){ while(~scanf("%d%d", &n, &m)){ for(int i = 0; i < n; i++){ scanf("%d", &a[i]); } init(); while(m--){ int o, l, r, z; scanf("%d%d%d%d", &o, &l, &r, &z); if(o == 1){ update(l, r, z); } else{ printf("%d\n", query(l, r, z)); } } } return 0; }