分块
今日新学—分块,但学得不好,只简单写写。
分块就是把结构中的的元素分成几块,因为要减少复杂度,块不能分太多也不能分太少,块数和每块内元素数接近最好,即块数约等于每块内元素数约等于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)。