数据结构专题-分块算法 区间加法 区间内x的前驱

1.区间加法,单点查询
Code:

#include <bits/stdc++.h>
#define LL long long
using namespace std;
int n, m ;
const int AX = 1e5+6;
int add[AX];
int a[AX];
int b[AX];
int len;

void update( int l , int r , int c ){
    int lim = min( r , b[l] * len );
    for( int i = l ; i <= lim ; i++ ){
        a[i] += c;
    }
    if( b[l] != b[r] ){
        for( int i = ( b[r] - 1 ) * len + 1 ; i <= r ; i++ ){
            a[i] += c;
        }
    }
    for( int i = b[l] + 1 ; i < b[r] ; i++ ) add[i] += c;
        return;
}

int main(){
    int n;
    scanf("%d",&n);
    int m = n;
    len = sqrt(n);
    for( int i = 1 ; i <= n ; i++ ){
        scanf("%d",&a[i]);
    }
    for( int i = 1 ; i <= n ; i++ ){
        b[i] = (( i - 1 ) / len) + 1 ;
    }
    int op,l,r,c;
    while( m-- ){
        scanf("%d%d%d%d",&op,&l,&r,&c);
        if( !op ){
            update( l , r , c );
        }else{
            int res = a[r] + add[b[r]] ;
            printf("%d\n",res);
        }
    }
    return 0 ;
}

2.给出一个长为n的数列,以及n个操作,操作0区间加法,操作1询问区间内小于某个值x的前驱(比其小的最大元素)。

Code:

#include <bits/stdc++.h>
using namespace std;
const int AX = 1e6+66;
set<int>s[AX];
int a[AX];
int b[AX];
int add[AX];
int len ;
void rebuild( int t ){
    s[t].clear();
    for( int i = ( t - 1 ) * len + 1 ; i <= t * len ; i++ ){
        s[t].insert( a[i] );
    }
    return;
}

void update( int l , int r , int c ){
    int lim = min( r , b[l] * len );
    for( int i = l ; i <= lim ; i++ ){
        a[i] += c;
    }
    rebuild( b[l] );
    if( b[l] != b[r] ){
        for( int i = ( b[r] - 1 ) * len + 1 ; i <= r ; i++ ){
            a[i] += c;
        }
        rebuild( b[r] );
    }
    for( int i = b[l] + 1 ; i < b[r] ; i++ ) add[i] += c;
    return;
}

int query( int l , int r , int c ){
    int res = -1;
    int lim = min( r , b[l] * len );
    for( int i = l ; i <= lim ; i++ ){
        int tmp = a[i] + add[b[i]];
        if( tmp < c ){
            res = max( res ,  tmp );    
        }
    }
    if( b[l] != b[r] ){
        for( int i = ( b[r] - 1 ) * len + 1 ; i <= r ; i++ ){
            int tmp = a[i] + add[b[i]];
            if( tmp < c ){
                res = max( res, tmp );
            }
        }
    }
    for( int i = b[l] + 1 ; i < b[r] ; i++ ){
        int tmp = c - add[i];
        set<int>::iterator it = s[i].lower_bound(tmp);
        if( it == s[i].begin() ) continue;
        it --;
        res = max( (*it) + add[i] , res );
    }
    return res ;
}

int main(){
    int n;
    scanf("%d",&n);
    int m = n;
    len = 1000;   //每块的长度。sqrt(n) 左右
    for( int i = 1 ; i <= n ; i++ ){
        scanf("%d",&a[i]);
    }
    for( int i = 1 ; i <= n ; i++ ){
        b[i] = (( i - 1 ) / len) + 1 ;
        s[b[i]].insert( a[i] );
    }
    int op,l,r,c;
    while( m-- ){
        scanf("%d%d%d%d",&op,&l,&r,&c);
        if( !op ){
            update( l , r , c );
        }else{
            int res = query(l,r,c) ;
            printf("%d\n/",res);
        }
    }
    return 0 ;
}

猜你喜欢

转载自blog.csdn.net/frankax/article/details/80344101