您的位置:首页 > 其它

【bzoj3211】花神游历各国

2016-08-11 15:27 274 查看
首先,单点修改求区间和可以用树状数组实现

因为开平方很耗时间,所以在这个方面可以优化

我们知道,开平方开几次之后数字就会等于1

所以,用数组记录下一个应该开的数,每次直接跳到下一个不是1的数字进行开平方,至于这个数组,可以用并查集维护。

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

typedef long long LL;

#define lowbit(x) (x&(-x))
#define N 100010

int n,m;
int ask,l,r,t;

int f
,a
;
LL c
;

inline int getint()
{
int x=0,f=1;
char ch=getchar();
while (ch>'9' || ch<'0')
{
if (ch=='-')
f=-1;
ch=getchar();
}
while (ch>='0' && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}

inline int find(int x)
{
return x==f[x] ? x : f[x]=find(f[x]);
}

inline void add(int x,int d)
{
while (x<=n)
c[x]+=d,x+=lowbit(x);
}

inline LL query(int x)
{
LL res(0);
while (x)
res+=c[x],x-=lowbit(x);
return res;
}

int main()
{
n=getint();
for (int i=1;i<=n;i++)
{
a[i]=getint();
f[i]=i;
add(i,a[i]);
}
f[n+1]=n+1;
m=getint();
while (m--)
{
ask=getint(),l=getint(),r=getint();
if (ask==1)
printf("%lld\n",query(r)-query(l-1));
else
for (int i=l;i<=r;add(i,(t=(int)sqrt(a[i]))-a[i]),a[i]=t,f[i]=(a[i]<=1) ? i+1 : i,i=(find(i)==i ? i+1 : f[i]));
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: