HDU 4638 分块Or树状数组

给你一个1~N的排列,问区间[L, R] 之间有多少段连续的数。比如区间里有3、1、2、5、6,这五个数,那么就有3、1、2和5、6这两段。

询问一个区间的时候,可以一个一个的向里面添加,只需要判断a[i]-1 和 a[i]+1是否已经添加在内,如果两个都在,则总段数减1,如果两个都不在,总段数加1,其他情况总段数不变了。



const int maxn = 100100 ;

struct  Q{
        int l , r , id , p ;
        friend bool operator < (const Q A , const Q B){
             if(A.p == B.p) return A.r < B.r ;
             else  return A.p < B.p ;
        }
}q[maxn + 8] ;

int  a[maxn + 8] ;
int  ans[maxn + 8] ;
int  L , R , sum ;
bool vis[maxn + 8] ;

void add(int x){
     vis[x] = 1 ;
     if(vis[x-1] && vis[x+1]) sum-- ;
     else if(!vis[x-1] && !vis[x+1]) sum++ ;
}

void del(int x){
     vis[x] = 0 ;
     if(vis[x-1] && vis[x+1]) sum++ ;
     else if(!vis[x-1] && !vis[x+1]) sum-- ;
}


int  ask(int l , int r , int id){
     int i ;
     if(id == 0){
         sum = 0 ;
         for(i = l ; i <= r ; i++)  add(a[i]) ;
         L = l , R = r ;
         return sum ;
     }
     for(i = l ; i < L ; i++) add(a[i]) ;
     for(i = R+1 ; i <= r ; i++) add(a[i]) ;
     for(i = L ; i < l ; i++) del(a[i]) ;
     for(i = r+1 ; i <= R ; i++) del(a[i]) ;
     L = l , R = r ;
     return sum ;
}

int  main(){
     int i , j , n  , m  , t ;
     int blocksize ;
     cin>>t ;
     while(t--){
          scanf("%d%d" , &n , &m) ;
          for(i = 1 ; i <= n ; i++) scanf("%d" ,&a[i]) ;
          blocksize = sqrt(0.5 + n) ;
          for(i = 0 ; i < m ; i++){
               scanf("%d%d" , &q[i].l , &q[i].r) ;
               q[i].id = i ;
               q[i].p = q[i].l / blocksize ;
          }
          memset(vis , 0 , sizeof(vis)) ;
          sort(q , q+m) ;
          for(i = 0 ; i < m ; i++)
              ans[q[i].id] = ask(q[i].l , q[i].r , i) ;
          for(i = 0 ; i < m ; i++) printf("%d\n" , ans[i]) ;
     }
     return 0 ;
}



#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <stdio.h>
#include <algorithm>
#include <map>
#include <math.h>
typedef long long LL ;

const int N = 100008 ;
int  n ;
namespace BIT{
    int val[N] ;
    int lowbit(int x){
        return x & (-x) ;
    }

    void add(int idx , int c){
         for(; idx <=n ; idx += lowbit(idx)) val[idx] += c ;
    }

    int sum(int idx){
        int res = 0 ;
        for(; idx ; idx -= lowbit(idx)) res += val[idx] ;
        return res ;
    }

    int sum(int l , int r){
        return sum(r) - sum(l-1) ;
    }

    void clear(){
         std::fill(val , val + 1 + n , 0) ;
    }
}

int  position[N] , a[N]  , vis[N] , res[N] ;
struct Query{
    int Lf , Rt , idx ;
    friend bool operator < (const Query &a , const Query &b){
         return a.Rt < b.Rt ;
    }
};
Query q[N] ;

int main(){
    std::ios::sync_with_stdio(false) ;
    int t , m ;
    scanf("%d" , &t) ;
    while(t--){
        scanf("%d%d" , &n , &m) ;
        for(int i = 1 ; i <= n ; i++){
            scanf("%d" , &a[i]) ;
            position[a[i]] = i ;
        }
        for(int i = 0 ; i < m ; i++){
            scanf("%d%d" , &q[i].Lf , &q[i].Rt ) ;
            q[i].idx = i ;
        }
        std::sort(q , q + m) ;

        BIT::clear() ;
        std::fill(vis , vis + 1 + n , 0) ;
        int idx = 0 ;
        for(int i = 1 ; i <= n ; i++){
            vis[a[i]] = 1 ;
            BIT::add(i , 1) ;
            if(vis[a[i]-1]) BIT::add(position[a[i]-1] , -1) ;
            if(vis[a[i]+1]) BIT::add(position[a[i]+1] , -1) ;
            while(idx < m && q[idx].Rt == i){
                 res[q[idx].idx] = BIT::sum(q[idx].Lf, q[idx].Rt) ;
                 idx++ ;
            }
        }
        for(int i = 0 ; i < m ; i++) printf("%d\n" , res[i]) ;
    }
    return 0 ;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值