线段树练习之——分块解法

来源:互联网 发布:广州淘宝进货都在哪里 编辑:程序博客网 时间:2024/06/03 16:10

orz xczhw大神

今天某大神跑过来跟我说来学分块吧,很有意思的
于是我就信了= =

对于一个点修改区间查询的数列,把原序列按照sqrt(n)大小为长度分块,每一个块处理它块内的权值和,要查询时,块内的暴力查询,块外直接使用预处理得到的结果sqrt(n)的时间内求出即可
这里写图片描述

设分块大小为M
如果查询点在一个块的头标记点(i%M),那么将这个点直接前进M步进入下一个块的头标记点即可
如果当前点在一个块内,但并不是头标记点,暴力把答案得出来即可

#include<iostream>#include<cstdio>#include<queue>#include<algorithm>#include<cmath>#include<cstring>using namespace std;const int maxn=2333333;int xl[maxn];int kuai[maxn];int n;void init(){    int y=sqrt(n);    for(int i=0;i<n;i++){        kuai[i/y]+=xl[i];    }}void change(int a,int v){    int y=sqrt(n);    xl[a]+=v;    kuai[a/y]+=v;}int ask(int a,int b){    int y=sqrt(n);    int ans=0;    while(a<=b){        if(!(a%y)&&a+y<=b){            ans+=kuai[a/y];            a+=y;        }        else{            ans+=xl[a];            a++;        }    }    return ans;}int main(){    cin>>n;    for(int i=0;i<n;i++){        scanf("%d",&xl[i]);    }    init();    //cout<<(int)sqrt(n)<<endl;    int m;    cin>>m;    for(int i=1;i<=m;i++){        int x,a,b;        scanf("%d%d%d",&x,&a,&b);        if(x==1){            change(a-1,b);        }        if(x==2){            if(a>b) swap(a,b);            cout<<ask(a-1,b-1)<<endl;        }    }    return 0;}
0 0
原创粉丝点击