BZOJ 4216: Pig

题目

红学姐和黄学长是好朋友。
有一天,黄学长想吃猪肉丸,于是他去找红学姐买猪。红学姐到她的猪圈中赶猪的
时候发现有许多猪逃离了她的猪圈。同时红学姐发现,一个名叫wwf的魔法猪藏在某
个猪圈中施法。然而wwf实在太巨了,红学姐并没有办法捉住它,只好向方老师求救。
为了确定wwf的位置,方老师向红学姐提出了m组询问,每次询问标号在区间[l,r]内
的猪圈剩余的猪的数量和,但红学姐不屑于做这些简单的问题,就把它们交给了你,同
时给了你一台内存较小的电脑。
由于wwf施展了一些奇怪的魔法,所以猪圈中猪的数量可能是负数。

分析

我居然在酒店刷题//丧心病狂//

扫了一遍题//居然没读懂,看了一波样例,没有问题,我知道他在说什么了,求个前缀和不就好了吗//但是//但是他只给3MB内存是什么鬼啊//

然后算了一波空间,发现似乎没什么大问题//但是,如果要long long的话不就炸了吗!!!

果断看题解//我们可以以15为大小来进行分块,对于一整块的,我们用前缀和来维护,直接拿就好,对于不是一整块的,我们暴力扫一遍就是了,然后这道题就被愉快的解决啦!

代码

#include 

#define N 500005
#define M 33335
#define K 16
#define ll long long

int a[N];
ll sum[M];
ll ans;

int n,m,t;

int l,r;

int cntB,Bl,Br;

void cal(int l,int r)
{
    Bl = l >> 4;
    Br = r >> 4;
    ans += sum[Br - 1] - sum[Bl];
    for (int i = l; i >> 4 == Bl && i > 0 && i <= n; i++)
    {
        ans += a[i];
    }
    for (int i = r; i >> 4 == Br && i > 0 && i <= n; i--)
    {
        ans += a[i];
    }
}

int main()
{
    scanf("%d%d%d",&n,&m,&t);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d",&a[i]);
        sum[i >> 4] += a[i];
    }
    cntB = n >> 4;
    for (int i = 1; i <= cntB; i++)
        sum[i] += sum[i -1];
    for (int i = 1; i <= m; i++)
    {
        scanf("%d%d",&l,&r);
        if (ans < 0) ans = -ans;
        if (t)
        {
            l = (l ^ ans) % n + 1;
            r = (r ^ ans) % n + 1;
            if (l > r)
                l ^= r ^= l ^= r;
        }
        ans = 0;
        cal(l,r);
        printf("%lld\n",ans);
    }
}

你可能感兴趣的:(分块)