SPOJ Can you answer these queries 系列
传送门
I:Can you answer these queries I
II:Can you answer these queries II
III:Can you answer these queries III
IV:Can you answer these queries IV
V:Can you answer these queries V
VI:Can you answer these queries VI
VII:Can you answer these queries VII
VIII:Can you answer these queries VIII
题解
Can you answer these queries I
Can you answer these queries I
Can you answer these queries II
Can you answer these queries II
Can you answer these queries III
Can you answer these queries III
Can you answer these queries IV
传送门:Can you answer these queries IV
重题:洛谷 P4145 上帝造题的七分钟2 / 花神游历各国
题目描述:区间开平方运算,并区间求和
算法分析:\(\sqrt{x}\) 向下取整,那么\(\forall x \in R\),在经过有限次开平方运算后,其结果一定为\(1\)。故只需将大于\(1\)的区间的数开平方即可,就能大大降低时间复杂度,然后在更新时只要递归修改即可(\(10^{18}\)至多需要6次修改),查询时区间查询。在这里用了两个数组:\(sum\) 和 \(maxi\),\(sum\)存储和,\(maxi\)储存区间最大值。若区间最大值 \(>1\),则需修改。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define G ch=getchar()
#define in(x) x=read()
using namespace std;
typedef long long ll;
inline ll read()
{
char ch=getchar();
ll num=0,f=1;
while((ch<'0' || ch>'9') && ch!='-') G;
if(ch=='-') {f=-1; G;}
while(ch>='0' && ch<='9') {num=num*10+ch-'0'; G;}
return num*f;
}
class segment_tree
{
#define ls k<<1
#define rs k<<1 | 1
#define mid ((l+r)>>1)
#define S(x) x=(int)sqrt(x)
#define SIZE 100000
public:
void clear() {memset(sum,0,sizeof(sum)); memset(maxi,0,sizeof(maxi));}
void update(int k,int l,int r,int ql,int qr)
{
if(l==r) {S(sum[k]); S(maxi[k]); return;}
if(ql<=mid && maxi[ls]>1) update(ls,l,mid,ql,qr);
if(qr>mid && maxi[rs]>1) update(rs,mid+1,r,ql,qr);
pushup(k);
}
ll query(int k,int l,int r,int ql,int qr)
{
if(ql<=l && r<=qr) return sum[k];
ll ans=0;
if(ql<=mid) ans+=query(ls,l,mid,ql,qr);
if(qr>mid) ans+=query(rs,mid+1,r,ql,qr);
return ans;
}
void build(int k,int l,int r)
{
if(l==r) {in(sum[k]); maxi[k]=sum[k]; return;}
build(ls,l,mid); build(rs,mid+1,r);
pushup(k);
}
private:
ll sum[4*SIZE+1],maxi[4*SIZE+1];
void pushup(int k) {sum[k]=sum[ls]+sum[rs]; maxi[k]=max(maxi[ls],maxi[rs]);}
#undef ls
#undef rs
#undef mid
#undef S
};
segment_tree tree;
int n,m,l,r,op,t;
void subtask(int);
int main()
{
while(~scanf("%d",&n)) {t++; subtask(t);}
return 0;
}
void subtask(int _case)
{
printf("Case #%d:\n",_case);
tree.clear();
tree.build(1,1,n); in(m);
for(register int i=1;i<=m;i++)
{
in(op); in(l); in(r);
if(l>r) swap(l,r);
if(op==0) tree.update(1,1,n,l,r);
else printf("%lld\n",tree.query(1,1,n,l,r));
}
printf("\n");
}
Can you answer these queries V
Can you answer these queries V
Can you answer these queries VI
Can you answer these queries VI
Can you answer these queries VII
Can you answer these queries VII