「分塊系列」數列分塊入門8 解題報告

數列分塊入門8

題意歸納

區間修改,區間計數。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入門

數列分塊入門4

數列分塊入門5

數列分塊入門6

數列分塊入門7

數列分塊入門8 <-

數列分塊入門9

蒲公英

公主的朋友

相關文章
相關標籤/搜索