hdu4027

hdu4027 Can you answer these queries?
传送门

题意

给出一个长度为\(n(1\leq n\leq 100000)\)的序列,序列中所有数的和不超过\(2^{63}\)。给出\(m(1\leq m\leq 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:\n",++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\n",query(1,1,n,l,r));
		}
		printf("\n");
	}
}
posted @ 2020-09-17 23:10  fxq1304  阅读(18)  评论(0编辑  收藏  举报