luogu P4145 上帝造题的七分钟2 / 花神游历各国 维护区间和&&区间开根号

Posted jackpei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P4145 上帝造题的七分钟2 / 花神游历各国 维护区间和&&区间开根号相关的知识,希望对你有一定的参考价值。

因为开根号能使数字减小得非常快

技术图片

所以开不了几次(6次?)很大的数就会变成1.....

所以我们可以维护区间最大值,若最大值>1,则继续递归子树,暴力修改叶节点,否则直接return

(好像也可以维护区间被开方的次数,但我不会。。。QAQ)

#include<cstdio>
#include<iostream>
#include<cmath>
#define int long long
#define R register int
#define ls (tr<<1)
#define rs (tr<<1|1)
using namespace std;
inline int g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch==-?-1:fix; 
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
}
int n,m;
int mx[400010],sum[400010];
inline void build(int tr,int l,int r){
    if(l==r) {mx[tr]=sum[tr]=g(); return ;} 
    R md=(l+r)>>1;
    build(ls,l,md),build(rs,md+1,r);
    mx[tr]=max(mx[ls],mx[rs]);
    sum[tr]=sum[ls]+sum[rs];
}
inline void calc(int tr,int l,int r,int ll,int rr) {
    if(mx[tr]<=1) return ;
    if(l==r) {mx[tr]=sqrt(mx[tr]),sum[tr]=sqrt(sum[tr]); return ;}
    R md=(l+r)>>1;
    if(ll>md) calc(rs,md+1,r,ll,rr);
    else if(rr<md+1) calc(ls,l,md,ll,rr);
    else calc(ls,l,md,ll,md),calc(rs,md+1,r,md+1,rr);
    mx[tr]=max(mx[ls],mx[rs]);
    sum[tr]=sum[ls]+sum[rs];
}
inline int query(int tr,int l,int r,int ll,int rr) {
    if(l==ll&&r==rr) return sum[tr];
    R md=(l+r)>>1;
    if(ll>md) return query(rs,md+1,r,ll,rr);
    else if(rr<md+1) return query(ls,l,md,ll,rr);
    else return query(ls,l,md,ll,md)+query(rs,md+1,r,md+1,rr);
}
signed main() {
    n=g(); build(1,1,n); m=g();
    for(R i=1,k,l,r;i<=m;++i) {
        k=g(),l=g(),r=g();
        if(l>r) swap(l,r);
        if(k&1) printf("%lld
",query(1,1,n,l,r));
        else calc(1,1,n,l,r);
    }
}

2019.04.11

 

以上是关于luogu P4145 上帝造题的七分钟2 / 花神游历各国 维护区间和&&区间开根号的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

[luogu] P4514 上帝造题的七分钟 (树状数组,二维差分)

luogu P4514ybtoj树状数组课堂过关差分 例题6区间修改区间查询 & 上帝造题的七分钟

BZOJ3038: 上帝造题的七分钟2