hdu4027 Can you answer these queries?
传送门
题意
给出一个长度为(n(1leq nleq 100000))的序列,序列中所有数的和不超过(2^{63})。给出(m(1leq mleq 100000))个操作或者询问,每次操作可以将区间([l,r])之中的数变为自身的平方根向下取整,每次询问查询区间([l,r])之中所有数的和。
题解
由于一个不超过(2^{63})的数经过(6)次平方根操作就可以成为(1),所以每次暴力修改区间内的数,当线段树节点的(tree[o]==(r-l+1)),说明节点区间内的所有数都已经成为(1),则停止修改。
#include<bits/stdc++.h>
#define LL long long
#define PII pair<int,int>
#define PLI pair<LL,int>
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lowbit(x) (x&(-x))
using namespace std;
const int maxn=100010;
int n,q,cas;
LL a[maxn],tree[4*maxn];
void pushup(int o){
tree[o]=tree[o<<1]+tree[o<<1|1];
}
void build(int o,int l,int r){
if(l==r){
tree[o]=a[l];
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
pushup(o);
}
void change(int o,int l,int r,int ql,int qr){
if(ql<=l && r<=qr){
if(tree[o]==(r-l+1)) return;
}
if(l==r){
tree[o]=sqrt(tree[o]);
return;
}
int mid=(l+r)>>1;
if(ql<=mid) change(lson,ql,qr);
if(qr>mid) change(rson,ql,qr);
pushup(o);
}
LL query(int o,int l,int r,int ql,int qr){
if(ql<=l && r<=qr) return tree[o];
int mid=(l+r)>>1;
LL ans=0;
if(ql<=mid) ans+=query(lson,ql,qr);
if(qr>mid) ans+=query(rson,ql,qr);
return ans;
}
int main(){
while(scanf("%d",&n)!=EOF){
printf("Case #%d:
",++cas);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
scanf("%d",&q);
while(q--){
int op,l,r;
scanf("%d %d %d",&op,&l,&r);
if(l>r) swap(l,r);
if(op==0) change(1,1,n,l,r);
else printf("%lld
",query(1,1,n,l,r));
}
printf("
");
}
}