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]);
}

时间: 2024-12-26 20:20:53

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

CodeVS2492 上帝造题的七分钟2(树状数组+并查集)

传送门 树状数组模板题.注意优化,假设某个数的值已经是1了的话.那么我们以后就不用对他进行操作了,这个能够用并查集实现. 这道题还有个坑的地方,给出查询区间端点的a,b,有可能a>b. #include<cstdio> #include<cmath> #include<cctype> #include<iostream> using namespace std; inline void GET(int &t){ char c; t=0; do{

[BZOJ3211]花神游历各国&amp;&amp;[BZOJ3038] 上帝造题的七分钟2 树状数组+并查集

3211: 花神游历各国 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 4057  Solved: 1480[Submit][Status][Discuss] Description Input Output 每次x=1时,每行一个整数,表示这次旅行的开心度 Sample Input 4 1 100 5 5 5 1 1 2 2 1 2 1 1 2 2 2 3 1 1 4 Sample Output 101 11 11 HINT 对于100%的数据,

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

题解:同 BZOJ 3211 花神游历各国,需要注意的是需要开long long,还有左右节点需要注意一下. #include <cstdio> #include <cmath> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; LL a[100005],c[100005]; int f[100005],n,m,op,l,r,t; int s

bzoj 3038: 上帝造题的七分钟2 线段树||hdu 4027

3038: 上帝造题的七分钟2 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1066  Solved: 476[Submit][Status][Discuss] Description XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部."第一分钟,X说,要有数列,于是便给定了一个正整数数列.第二分钟,L说,要能修改,于是便有了对一段数中每个数都开平方(下取整)的操作.第三分钟,k说,要能查询,于是便有了求一段数的和的操作.第四分

BZOJ 3038: 上帝造题的七分钟2【线段树区间开方问题】

3038: 上帝造题的七分钟2 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1469  Solved: 631[Submit][Status][Discuss] Description XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是便有了对一段数中每个数都开平方(下取整)的操作. 第三分钟,k说,要能查询,于是便有了求一段数的和的操作.

BZOJ 3038 上帝造题的七分钟2

我们发现每个数被开平方的次数不是太多. 然后1开平方还是1. 然后怎么办? 暴力啊!只要找到没有1的地方暴力做就可以了. #include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define maxn 100500using namespace std;long long ls[maxn<<3],rs[maxn<<3],value[maxn<<3

【BZOJ】3038 上帝造题的七分钟2

[算法]线段树||(坑...) [题解]修改必须暴力单点修改,然后利用标记区间查询. 优化:一个数经过不断开方很快就会变成1,所以维护区间最大值. 修改时访问到的子树最大值<=1时,该区间就不必修改. #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn=100010; struct treess{int k,l,r;long long ma

3038: 上帝造题的七分钟2 [线段树 暴力]

3038: 上帝造题的七分钟2 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1210  Solved: 536[Submit][Status][Discuss] Description XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部."第一分钟,X说,要有数列,于是便给定了一个正整数数列.第二分钟,L说,要能修改,于是便有了对一段数中每个数都开平方(下取整)的操作.第三分钟,k说,要能查询,于是便有了求一段数的和的操作.第四分

3038: 上帝造题的七分钟2

3038: 上帝造题的七分钟2 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 662  Solved: 302[Submit][Status] Description XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部."第一分钟,X说,要有数列,于是便给定了一个正整数数列.第二分钟,L说,要能修改,于是便有了对一段数中每个数都开平方(下取整)的操作.第三分钟,k说,要能查询,于是便有了求一段数的和的操作.第四分钟,彩虹喵说,要是n