• 上帝造题的七分钟2 / 花神游历各国(分块)


    好吧,楼下有分块的解法,那么我就再阐述一遍好了

    本以为暴力分块为(TLE)的,结果发现吊打线段树,用奇技淫巧的卡常技术卡到第一页

    评测记录

    其实这道题就是数列分块入门(5)嘛,发现一个数只能被不超过(6)次开方,那么暴力修改,用一个标记看看整块是否有大于(1)的数

    那么我就献上一个未卡常的分块解法

    (Code Below:)

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=100000+10;
    ll n,m,a[maxn],sum[330],v[330],pos[maxn],blo;
    
    void change(ll x){
        if(!v[x]){
            v[x]=1;sum[x]=0;
            for(ll i=(x-1)*blo+1;i<=x*blo;i++){
                a[i]=sqrt(a[i]);
                sum[x]+=a[i];
                if(a[i]>1) v[x]=0;
            }
        }
    }
    
    void update(ll l,ll r){
        if(!v[pos[l]]){
            for(ll i=l;i<=min(pos[l]*blo,r);i++){
                sum[pos[i]]-=a[i];
                a[i]=sqrt(a[i]);
                sum[pos[i]]+=a[i];
            }
            v[pos[l]]=1;
            for(ll i=(pos[l]-1)*blo+1;i<=min(pos[l]*blo,n);i++){
                if(a[i]>1){v[pos[l]]=0;break;}
            }
        }
        if(pos[l]!=pos[r]){
            if(!v[pos[r]]){
                for(ll i=(pos[r]-1)*blo+1;i<=r;i++){
                    sum[pos[i]]-=a[i];
                    a[i]=sqrt(a[i]);
                    sum[pos[i]]+=a[i];
                }
                v[pos[r]]=1;
                for(ll i=(pos[r]-1)*blo+1;i<=min(pos[r]*blo,n);i++){
                    if(a[i]>1){v[pos[r]]=0;break;}
                }
            }
        }
        for(ll i=pos[l]+1;i<=pos[r]-1;i++) change(i);
    }
    
    ll query(ll l,ll r){
        ll ans=0;
        for(ll i=l;i<=min(pos[l]*blo,r);i++) ans+=a[i];
        if(pos[l]!=pos[r])
            for(ll i=(pos[r]-1)*blo+1;i<=r;i++) ans+=a[i];
        for(ll i=pos[l]+1;i<=pos[r]-1;i++) ans+=sum[i];
        return ans;
    }
    
    int main()
    {
        scanf("%lld",&n);blo=sqrt(n);
        for(ll i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            pos[i]=(i-1)/blo+1;
            sum[pos[i]]+=a[i];
        }
        scanf("%lld",&m);
        ll opt,l,r;
        while(m--){
            scanf("%lld%lld%lld",&opt,&l,&r);
            if(l>r) swap(l,r);
            if(opt==0) update(l,r);
            else printf("%lld
    ",query(l,r));
        }
        return 0;
    }
    
  • 相关阅读:
    告别零码软件
    win+mingw+libxml2试用笔记
    beacon with java 1.7 on fedora
    mininet指令详解
    java Socket完美实例
    gnome3 下 qt 应用极其丑陋的解决方案
    org.apache.log4j Class Level
    Mac如何修改文本文件编码
    unity性能优化相关
    平面图判定
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/9736440.html
Copyright © 2020-2023  润新知