首页 > 代码库 > BZOJ 3038 上帝造题的七分钟2 树状数组+并查集

BZOJ 3038 上帝造题的七分钟2 树状数组+并查集

题目大意:一个序列,有两种操作,1.将一段数中的每一个数开根号。2.查询一段数的和。


思路:和3211是一个题,有兴趣的可以看看我的那篇博客。


CODE:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
using namespace std;

int cnt,asks;
long long src[MAX];
long long fenwick[MAX];

int father[MAX];

void Pretreatment();

inline void Fix(int x,long long c);
inline long long GetSum(int x);

int Find(int x);

int main()
{
	cin >> cnt;
	Pretreatment();
	for(int i = 1;i <= cnt; ++i) {
		scanf("%lld",&src[i]);
		Fix(i,src[i]);
		if(src[i] == 1)	father[i] = i + 1;
	}
	cin >> asks;
	for(int flag,x,y,i = 1;i <= asks; ++i) {
		scanf("%d%d%d",&flag,&x,&y);
		if(x > y)	swap(x,y);
		if(!flag)
			for(x = Find(x);x <= y;x = Find(x + 1)) {
				Fix(x,-src[x]);
				Fix(x,src[x] = sqrt(src[x]));
				if(src[x] == 1)	father[x] = Find(x + 1);
			}
		else	printf("%lld\n",GetSum(y) - GetSum(x - 1));
	}
	return 0;
}

void Pretreatment()
{
	for(int i = 1;i <= cnt + 1; ++i)
		father[i] = i;
}

inline void Fix(int x,long long c)
{
	for(int i = x;i <= cnt;i += i&-i)
		fenwick[i] += c;
}

inline long long GetSum(int x)
{
	long long re = 0;
	for(int i = x;i;i -= i&-i)
		re += fenwick[i];
	return re;
}

int Find(int x)
{
	if(father[x] == x)	return x;
	return father[x] = Find(father[x]);	
}


BZOJ 3038 上帝造题的七分钟2 树状数组+并查集