题解 SP2713 GSS4 - Can you answer these queries IV
Posted lhm-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 SP2713 GSS4 - Can you answer these queries IV相关的知识,希望对你有一定的参考价值。
用计算器算一算,就可以发现(10^{18})的数,被开方(6)次后就变为了(1)。
所以我们可以直接暴力的进行区间修改,若这个数已经到达(1),则以后就不再修改(因为(1)开方后还是(1)),用并查集和树状数组进行维护。
这个方法用了P2391 白雪皑皑的思想处理,用并查集标记该点已经不再用替换。
和我这题CF920F【SUM和REPLACE】的方法相同。
(code):
#include<bits/stdc++.h>
#define maxn 500010
#define lowbit(x) (x&(-x))
typedef long long ll;
using namespace std;
ll n,m;
ll fa[maxn],k,l,r;
ll a[maxn],tree[maxn];
int cnt;
int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void add(int x,ll d)
{
while(x<=n)
{
tree[x]+=d;
x+=lowbit(x);
}
}
ll query(int x)
{
ll sum=0;
while(x)
{
sum+=tree[x];
x-=lowbit(x);
}
return sum;
}
int main()
{
while(scanf("%lld",&n)!=EOF)
{
cnt++;
printf("Case #%d:
",cnt);
for(int i=1;i<=n*4;++i)
tree[i]=0;
for(int i=1;i<=n;++i)
{
scanf("%lld",&a[i]);
add(i,a[i]);
fa[i]=i;
}
fa[n+1]=n+1;
scanf("%lld",&m);
while(m--)
{
scanf("%lld%lld%lld",&k,&l,&r);
if(l>r)
swap(l,r);
if(k==0)
{
for(int i=l;i<=r;)
{
add(i,(ll)sqrt(a[i])-a[i]);//手动暴力开方
a[i]=(ll)sqrt(a[i]);
if(a[i]<=1)
fa[i]=i+1;//若这个数已经为1,则将其指向它下一个数
if(i==find(i))
i++;
else
i=fa[i];//进行跳转,忽略不再需要开方的数
}
}
else
printf("%lld
",query(r)-query(l-1));
}
printf("
");
}
return 0;
}
以上是关于题解 SP2713 GSS4 - Can you answer these queries IV的主要内容,如果未能解决你的问题,请参考以下文章
SP2713 GSS4 - Can you answer these queries IV
SP2713 GSS4 - Can you answer these queries IV(线段树)
「SP2713」GSS4 - Can you answer these queries IV
spoj GSS4 - Can you answer these queries IV