• P4145 上帝造题的七分钟2 / 花神游历各国 题解


    CSDN同步

    原题链接

    简要题意:

    给定一个长为 (n) 的序列 (a)(q) 次操作:

    • ([l,r]) 区间进行开平方操作。即 (a_i gets lfloor sqrt{a_i} floor (i in [l,r]))..
    • 询问 ([l,r]) 区间的和。即 (a_{i=l}^r) 的和。

    (n,q leq 10^5), (1 leq a_i leq 10^{12})

    我们注意到一个性质:

    开平方操作数将会很快变成 (1). 即使是 (10^{12}),在 六次开平方操作之后 也变成了 (1).

    所以修改操作 有效的次数 很少,我们最多只需要对每个数进行 (6) 次修改,其余的情况就可以忽略不计。

    我们可以维护前缀和 (s),暴力维护!但如果 (a_{i=l}^r a_i = r - l + 1),说明 (a_i = 1 (i in [l,r])),那么可以跳过这个操作。

    时间复杂度:(mathcal{O}(n)).

    实际得分:(100pts).

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int N=1e5+1;
    
    inline ll read(){char ch=getchar(); int f=1; while(!isdigit(ch)) {if(ch=='-') f=-f; ch=getchar();}
    	   ll x=0;while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*f;}
    
    int n,q;
    ll a[N],s[N];
    
    int main() {
    	n=read();
    	for(int i=1;i<=n;i++) a[i]=read(),s[i]=s[i-1]+a[i];
    	q=read(); while(q--) {
    		int op=read(),l=read(),r=read();
    		if(l>r) swap(l,r); //细节
    		if(!op) {
    			if(s[r]-s[l-1]==r-l+1) continue;
    			else
    				for(int i=l;i<=n;i++) {
    					if(i<=r) a[i]=sqrt(a[i]);
    					s[i]=s[i-1]+a[i];
    				} //暴力维护
    
    		} else printf("%lld
    ",s[r]-s[l-1]);
    	}
    	return 0;
    }
    
    
    
    

    后记

    这个题可以用线段树等维护前缀和 (s),还可以大力线段树。不过,本来修改只有 (6) 次有效,暴力也不怕!是不是!

  • 相关阅读:
    第一次 实习笔记
    docker 提示 Drive has not been shared 错误
    使用matplotlib画出log的图像
    python基础实现tcp文件传输
    django简单实现注册登录模块
    python使用消息队列RabbitMq(进阶)
    scrapy爬虫值Items
    redis常见配置redis.conf
    js实现往数组中添加非存在的对象,如果存在就改变键值。
    CSS之user-select——设置标签中的文字是否可被复制
  • 原文地址:https://www.cnblogs.com/bifanwen/p/13336681.html
Copyright © 2020-2023  润新知