Loj#6281. 数列分块入门 5

给出一个长为 n 的数列,以及 n 个操作,操作涉及区间开方,区间求和。

样例输入

4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4

样例输出

 6

2
分析:这道题没办法维护整块的信息,必须要知道每一个元素具体是多少才行.
   开方的一个性质:2 ^ 32内的数最多经过6次开方就变成了0或1,也就是说一个数最多只会被修改6次. 分块维护当前区间是不是全是0/1,是的话就跳过修改这个区间.
   数组开小导致一直WA......
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll maxn = 50010;
ll n,a[maxn],sum[maxn],pos[maxn],block,L[maxn],R[maxn],cnt;
bool flag[maxn];

void modify(ll x)
{
    if (flag[x])
        return;
    flag[x] = 1;
    sum[x] = 0;
    for (ll i = L[x]; i <= R[x]; i++)
    {
        a[i] = sqrt(a[i]);
        sum[x] += a[i];
        if (a[i] > 1)
            flag[x] = 0;
    }
}

void update(ll l,ll r)
{
    if (pos[l] == pos[r])
    {
        for (ll i = l; i <= r; i++)
        {
            sum[pos[l]] -= a[i];
            a[i] = sqrt(a[i]);
            sum[pos[l]] += a[i];
        }
        return;
    }
    for (ll i = l; i <= R[pos[l]]; i++)
    {
        sum[pos[l]] -= a[i];
        a[i] = sqrt(a[i]);
        sum[pos[l]] += a[i];
    }
    for (ll i = L[pos[r]]; i <= r; i++)
    {
        sum[pos[r]] -= a[i];
        a[i] = sqrt(a[i]);
        sum[pos[r]] += a[i];
    }
    for (ll i = pos[l] + 1; i <= pos[r] - 1; i++)
        modify(i);
}

ll query(ll l,ll r)
{
    ll res = 0;
    if (pos[l] == pos[r])
    {
        for (ll i = l; i <= r; i++)
            res += a[i];
        return res;
    }
    for (ll i = l; i <= R[pos[l]]; i++)
        res += a[i];
    for (ll i = L[pos[r]]; i <= r; i++)
        res += a[i];
    for (ll i = pos[l] + 1; i <= pos[r] - 1; i++)
        res += sum[i];
    return res;
}

int main()
{
    scanf("%lld",&n);
    block = sqrt(n);
    for (ll i = 1; i <= n; i++)
    {
        scanf("%lld",&a[i]);
        pos[i] = (i - 1) / block + 1;
    }
    cnt = (n - 1) / block + 1;
    for (ll i = 1; i <= cnt; i++)
    {
        L[i] = R[i - 1] + 1;
        R[i] = min(n,block * i);
        for (ll j = L[i]; j <= R[i]; j++)
            sum[i] += a[j];
    }
    for (ll i = 1; i <= n; i++)
    {
        ll opt,l,r,c;
        scanf("%lld%lld%lld%lld",&opt,&l,&r,&c);
        if (opt == 0)
            update(l,r);
        else
            printf("%lld\n",query(l,r));
    }

    return 0;
}

 

 
posted @ 2018-03-13 13:42  zbtrs  阅读(122)  评论(0编辑  收藏  举报