BZOJ 3211: 花神游历各国 |树状数组|并查集

树状数组维护前缀和

并查集维护从一个点向后(包括这个点)第一个权值>1的点

因为权值<=1更新是没有必要的

而开根号一个int的数顶多开5次就成了1

复杂度是nlogn的

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#define lowbit(x) x&(-x)
#define T 100010
using namespace std;
int sc()
{
	int i=0,f=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
	return i*f;
}
long long tr[T];
int nxt[T],a[T];
int n,m;
int find(int x){return nxt[x]==x?x:nxt[x]=find(nxt[x]);}
void change(int x,int f){ for(;x<=n;x+=lowbit(x))tr[x]+=f; }
void solve(int l,int r)
{
	for(int i=find(nxt[l]);i<=r;i=find(nxt[i+1]))
	{
		int x=(int)sqrt(a[i]);
		change(i,x-a[i]);
		a[i]=x;
		if(a[i]<=1)nxt[i]=find(nxt[i+1]);
	}
}
long long ask(int x)
{
	long long ans=0;
	for(;x;x-=lowbit(x)) ans+=tr[x];
	return ans;
}
int main()
{
	n=sc();
	for(int i=1;i<=n;i++)a[i]=sc(),change(i,a[i]);
	for(int i=1;i<=n;i++)nxt[i]=i;nxt[n+1]=n+1;
	m=sc();
	for(int i=1;i<=m;i++)
	{
		int x=sc(),a=sc(),b=sc();
		if(x==2) solve(a,b);
		else     printf("%lld\n",ask(b)-ask(a-1));
	}
	return 0;
}
	


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值