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;
    }
     
  • 相关阅读:
    Linux学习笔记——虚拟机VMWare和Ubuntu的安装
    毕业大论文格式排版(页眉页脚)Issue及解决办法
    NAT详解
    ARP是如何工作的?
    以太网,IP,TCP,UDP数据包分析
    mac os 10.10下安装android studio问题:android studio was unable to find a valid jvm
    Fragment的生命周期&同一Activity下不同Fragment之间的通信
    Android开发:碎片Fragment完全解析fragment_main.xml/activity_main.xml
    Android系统中长按事件的实现机制解析
    Linux 系统库函数coreleft 与sbrk简介
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8556190.html
Copyright © 2011-2022 走看看