[BZOJ4216]Pig(分块)

题目描述

传送门

题解

这题卡内存,不能直接用前缀和
分块的话也只能开一些大小为块的个数的数组
难度不是很大,只需要做的时候小心一些就行了
不过ATP嫌我跑的太慢告诉我了一个较科学的方法,就是将块做一个前缀和,然后把块开小一点

代码

#include<algorithm>
#include<cstdio>
using namespace std;
#define LL long long

int n,m,opt,t,block,num,numl,numr;
int a[500005],L[800],R[800];
LL l,r,ans;
LL sum[800];

void query(int l,int r)
{
    numl=(l-1)/block+1,numr=(r-1)/block+1;
    if (numl==numr)
    {
        for (int i=l;i<=r;++i) ans+=(LL)a[i];
        return;
    }
    if (l==L[numl]) l=numl;
    else
    {
        for (int i=l;i<=R[numl];++i)
            ans+=(LL)a[i];
        l=numl+1;
    }
    if (r==R[numr]) r=numr;
    else
    {
        for (int i=L[numr];i<=r;++i)
            ans+=(LL)a[i];
        r=numr-1;
    }
    for (int i=l;i<=r;++i) ans+=sum[i];
    return;
}
int main()
{
    scanf("%d%d%d",&n,&m,&opt);
    for (int i=1;i<=n;++i) scanf("%d",&a[i]);
    block=707;t=(n-1)/block+1;
    L[1]=1,R[1]=block;
    for (int i=2;i<=t;++i)
    {
        L[i]=L[i-1]+block;
        R[i]=R[i-1]+block;  
    }R[t]=n;
    for (int i=1;i<=t;++i)
        for (int j=L[i];j<=R[i];++j)
            sum[i]+=(LL)a[j];
    for (int i=1;i<=m;++i)
    {
        scanf("%lld%lld",&l,&r);
        if (ans<0) ans=-ans;
        if (opt)
        {
            l=(l^ans)%n+1;
            r=(r^ans)%n+1;
            if (l>r) swap(l,r);
        }
        ans=0LL;query(l,r);
        printf("%lld\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值