mthoutai

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

题意:链接

方法:分块以节约空间。

解析:

这题坑的地方就是他仅仅有3M的内存限制,假设我们开longlong前缀和是必死的。

所以考虑缩小这个long long数组的大小。

然后想到分块

最好还是以15为大小进行分块,事实上不T再大一点也行,可是算内存的话15是差点儿相同的吧。

然后记录每一个块内的和,然后询问的时候整块直接拿,非整块暴力枚举。顶多30个点。

所以时间上能过,然后内存上也就2.6MB左右。能够过。

可是有个问题啊,千万别打using namespace std;

这个执行自己主动申请700kb内存。太坑辣!

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 500005
#define M 33335
#define K 16
typedef long long ll;
int a[N];
ll sum[M];
int n,m,jd,blockl,blockr,cntblock,l,r;
ll ans;
void calc(int l,int r)
{
    blockl=l>>4;
    blockr=r>>4;
    ans+=sum[blockr-1]-sum[blockl];
    for(int i=l;i>>4==blockl&&i>0&&i<=n;i++)
    {
        ans+=a[i];
    }
    for(int i=r;i>>4==blockr&&i>0&&i<=n;i--)
    {
        ans+=a[i];
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&jd);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        sum[i>>4]+=a[i];
    }
    cntblock=n>>4;
    for(int i=1;i<=cntblock;i++)sum[i]+=sum[i-1];
    for(int i=1;i<=m;i++)
    {
        if(ans<0)ans=-ans;
        scanf("%d%d",&l,&r);
        if(jd)
        {
            l=(l^ans)%n+1;
            r=(r^ans)%n+1;
            if(l>r)
                l^=r^=l^=r;
        }
        ans=0;calc(l,r);
        printf("%lld\n",ans);
    }
}
posted on 2017-07-29 16:59  mthoutai  阅读(246)  评论(0编辑  收藏  举报