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;
    }
     
  • 相关阅读:
    COCO2018 目标检测
    最小生成树[摘录自严长生老师的网站]
    PANet训练自己的数据(VIA标注)
    图的遍历[摘录自严长生老师的网站]
    图的链式存储(邻接表)【摘录自严长生老师的网站】
    Android写入到mysql里的中文总是乱码?
    Mac 当xampp里mysql无法启动的解决办法
    【代码段】Android Studio使用DatePicker选择日期
    Android jdbc连接mysql报错解决方案 (Communications link failure)
    绝命毒师口语精析(4)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8556190.html
Copyright © 2011-2022 走看看