CODECHEF Chef and Churus - 分块

是个论文题
题目大意,给定n个数字和n个区间,每次修改一个数字的权值或者询问一段区间的区间的和。
考虑分块,记录ans[i]表示询问第i块的答案,con[i][j]表示第i块的若干区间有多少包含位置j,那么每次A[x]加上y就会使得ans[i]+=con[i][x]*y
考虑询问零散的块怎么办,就是一个单点修改区间求和,直接做带log,考虑修改只有q次,但是询问有nsqrt(q)次,因此维护用分块维护前缀和即可,这样就只有根号了。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define ull unsigned long long
#define N 100010
#define BC 500
#define gc getchar()
using namespace std;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct black_box_of_data_structer{
    int sz,bc,n,L[BC],R[BC],bel[N];ull tag[BC],val[N];
    inline int init(int *a,int _n)
    {
        n=_n,sz=sqrt(n+0.5),bc=(n-1)/sz+1;
        for(int i=1;i<=bc;i++)
        {
            L[i]=(i-1)*sz+1,R[i]=min(i*sz,n),tag[i]=0;
            for(int j=L[i];j<=R[i];j++) val[j]=val[j-1]+a[j],bel[j]=i;
        }
        return 0;
    }
    inline int update(int p,int v)
    {
        for(int i=bel[p]+1;i<=bc;i++) tag[i]+=v;
        for(int i=p;i<=R[bel[p]];i++) val[i]+=v;
        return 0;
    }
    inline ull query(int p) { return val[p]+tag[bel[p]]; }
    inline ull query(int l,int r) { return query(r)-query(l-1); }
}ds;
int l[N],r[N],a[N],bel[N],L[BC],R[BC],con[BC][N];ull ans[BC];
int main()
{
    int n=inn();
    for(int i=1;i<=n;i++) a[i]=inn();ds.init(a,n);
    for(int i=1;i<=n;i++) l[i]=inn(),r[i]=inn();
    int sz=sqrt(n+0.5),bc=(n-1)/sz+1;
    for(int i=1;i<=bc;i++)
    {
        L[i]=(i-1)*sz+1,R[i]=min(i*sz,n);
        for(int j=L[i];j<=R[i];j++)
            bel[j]=i,ans[i]+=ds.query(l[j],r[j]),
            con[i][l[j]]++,con[i][r[j]+1]--;
        for(int j=1;j<=n;j++) con[i][j]+=con[i][j-1];
    }
    int q;scanf("%d",&q);
    while(q--)
        if(inn()==1)
        {
            int x=inn(),y=inn(),z=y;
            z=y-a[x],a[x]=y,y=z,ds.update(x,y);
            for(int i=1;i<=bc;i++) ans[i]+=(ull)con[i][x]*y;
        }
        else{
            int x=inn(),y=inn(),bx=bel[x],by=bel[y];ull Ans=0;
            if(bx==by) for(int i=x;i<=y;i++) Ans+=ds.query(l[i],r[i]);
            else{
                for(int i=bx+1;i<by;i++) Ans+=ans[i];
                for(int i=x;i<=R[bx];i++) Ans+=ds.query(l[i],r[i]);
                for(int i=L[by];i<=y;i++) Ans+=ds.query(l[i],r[i]);
            }
            printf("%llu\n",Ans);
        }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/81359886