BZOJ 3211 花神游历各国

来源:互联网 发布:男士皮鞋 知乎 编辑:程序博客网 时间:2024/06/10 08:37

是一道。。。很奇葩的题。

想了二十分钟合并递推lazy标记,结果发现答案这么狗血

大概就是,对于每个数,最多log次就成1(或本身为0),然后再sqrt就没有意义了,对答案没有任何影响,于是记录一下最大值,遇到最大值<=1的就没有更新的必要了,直接跳过就好。


#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>#include<algorithm>using namespace std;const int maxn=100005; struct tree{long long val;int maxi;}t[maxn<<2];void maintain(int ro){t[ro].val=t[ro<<1].val+t[ro<<1|1].val;t[ro].maxi=max(t[ro<<1].maxi,t[ro<<1|1].maxi);}void build(int ro,int l,int r){if(l==r){int a;scanf("%d",&a);t[ro].maxi=t[ro].val=a;return;}int mid=l+r>>1;build(ro<<1,l,mid);build(ro<<1|1,mid+1,r);maintain(ro);}void square(int ro,int L,int R,int l,int r){if(t[ro].maxi<=1)return;if(l==r){t[ro].maxi=t[ro].val=sqrt(t[ro].val);return;}int mid=l+r>>1;if(R<=mid)square(ro<<1,L,R,l,mid);else if(L>=mid+1)square(ro<<1|1,L,R,mid+1,r);else square(ro<<1,L,mid,l,mid),square(ro<<1|1,mid+1,R,mid+1,r);maintain(ro);}long long query(int ro,int L,int R,int l,int r){if(l==L&&r==R)return t[ro].val;int mid=l+r>>1;if(R<=mid)return query(ro<<1,L,R,l,mid);else if(L>=mid+1)return query(ro<<1|1,L,R,mid+1,r);else return query(ro<<1,L,mid,l,mid)+query(ro<<1|1,mid+1,R,mid+1,r);}int main(){int n,q;scanf("%d",&n);build(1,1,n);scanf("%d",&q);while(q--){int d,d1,d2;scanf("%d%d%d",&d,&d1,&d2);if(d==1)printf("%lld\n",query(1,d1,d2,1,n));else square(1,d1,d2,1,n);}return 0;}