區間修改,區間計數。html
感嘆~ 分塊真是玄之又玄|( ̄0 ̄)c++
跟分塊7相似的是,這題也運用還原。數組
v數組用來記錄一個分塊是否都爲一個數,f數組來記錄若是都爲一個數,那麼這個數是什麼(實際上能夠用只一個數組來記錄QAQ)spa
查詢時,對於都爲一個數的塊,直接加上(若是這個數是c),順便把f改成c,不是的話暴力計數,順便把v改成1,f改成c。code
不完整的塊稍微麻煩一點,若是v爲1的話先還原(都變成f的值),而後再修改~htm
#include<bits/stdc++.h> using namespace std; #define MAXN 100005 int n, d; int a[MAXN], b[MAXN], f[500]; bool v[500]; int FF( int x ){//取出x位置的值 return v[b[x]] ? f[b[x]] : a[x]; } int fun( int l, int r, int c ){//計數&修改 int ans(0); for ( int i = l; i <= r && i <= n; ++i ) ans += FF(i) == c, a[i] = c; return ans; } int Get( int l, int r, int c ){ int ans(0); if ( b[l] == b[r] ){ if ( v[b[l]] && f[b[l]] == c ) return r - l + 1; if ( v[b[l]] ){ fun( ( b[l] - 1 ) * d + 1, l - 1, f[b[l]] ); fun( r + 1, b[l] * d, f[b[l]] ); } ans = fun( l, r, c ); v[b[l]] = 0; return ans; } if ( v[b[l]] ) fun( ( b[l] - 1 ) * d + 1, l - 1, f[b[l]] ); ans += fun( l, b[l] * d, c ); v[b[l]] = 0; if ( v[b[r]] ) fun( r + 1, min( b[r] * d, n ), f[b[r]] ); ans += fun( ( b[r] - 1 ) * d + 1, r, c ); v[b[r]] = 0; for ( int i = b[l] + 1; i <= b[r] - 1; ++i ){ if ( !v[i] ){ for ( int j = ( i - 1 ) * d + 1; b[j] == i; ++j ) ans += a[j] == c, a[j] = c; v[i] = 1; f[i] = c; } else{ if ( f[i] == c ) ans += d; else f[i] = c; } } return ans; } int main(){ scanf( "%d", &n ); d = (int)sqrt(n); for ( int i = 1; i <= n; ++i ){ scanf( "%d", &a[i] ); b[i] = ( i - 1 ) / d + 1; } for ( int i = 1; i <= n; ++i ){ int l, r, c; scanf( "%d%d%d", &l ,&r, &c ); printf( "%d\n", Get( l, r, c ) ); } return 0; }
分塊大法好!\(^分_塊\le^靈_活的暴力\le^騙_分大法\)blog
數列分塊入門1get
數列分塊入門2it
數列分塊入門3入門
數列分塊入門8 <-