zoukankan      html  css  js  c++  java
  • 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
    ",query(l,r));
        }
    
        return 0;
    }
     
  • 相关阅读:
    88. Merge Sorted Array
    87. Scramble String
    86. Partition List
    85. Maximal Rectangle
    84. Largest Rectangle in Histogram
    83. Remove Duplicates from Sorted List
    82. Remove Duplicates from Sorted List II
    81. Search in Rotated Sorted Array II
    80. Remove Duplicates from Sorted Array II
    计算几何——点线关系(叉积)poj2318
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8556190.html
Copyright © 2011-2022 走看看