分块

今日新学—分块,但学得不好,只简单写写。

分块就是把结构中的的元素分成几块,因为要减少复杂度,块不能分太多也不能分太少,块数和每块内元素数接近最好,即块数约等于每块内元素数约等于sqrt(n)(总元素数为n)。

分块中处理两个问题时复杂度会降低——

1.区间修改

long long v,u,w;
cin>>v>>u>>w;
int
kv=(v-1)/ge+1;//kv代表v所在第几个块中,ku同理 int ku=(u-1)/ge+1;//ge代表正常块中元素个数
//u,v在同一块中
if(kv==ku){   for(int i=v;i<=u;i++){     a[i]+=w;
  }   kuai[kv].he
+=(u-v+1)*w;
}
//u,v在不同块中
else{
  //修改零散位置   kuai[kv].he
+=(kuai[kv].r-v+1)*w;   kuai[ku].he+=(u-kuai[ku].l+1)*w;   for(int i=v;i<=kuai[kv].r;i++){     a[i]+=w;
  }   
for(int i=kuai[ku].l;i<=u;i++){     a[i]+=w;
  }
  //修改整块位置   
for(int i=kv+1;i<=ku-1;i++){
    kuai[i].he
+=ge*w;//he代表块中所有元素数值的和     kuai[i].tag+=w;//tag代表整块同时增加的数值   }
}

2.区间查询

int v,u;
cin>>v>>u;
int kv=(v-1)/ge+1;
int ku=(u-1)/ge+1;
long long sum=0;
if(kv==ku){
    for(int i=v;i<=u;i++){
        sum+=a[i]+kuai[kv].tag;
    }
}
else{
    sum+=(kuai[kv].r-v+1)*kuai[kv].tag;
    sum+=(u-kuai[ku].l+1)*kuai[ku].tag;
    for(int i=v;i<=kuai[kv].r;i++){
        sum+=a[i];
    }
    for(int i=kuai[ku].l;i<=u;i++){
        sum+=a[i];
    }
    for(int i=kv+1;i<=ku-1;i++){
        sum+=kuai[i].he;
    }
}
cout<<sum<<endl;

通过以上代码可以发现分块算法是快在整块修改时将块中元素全部加这个值转变成块中记录整块加值,复杂度由O(sqrt(n))变为O(1)。

posted @ 2022-02-09 19:22  zzzzzz2  阅读(89)  评论(0编辑  收藏  举报