BZOJ 3211: 花神游历各国/BZOJ 3038: 上帝造题的七分钟2 树状数组+并查集

时间:2022-03-17 16:06:31

3211: 花神游历各国

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 3311  Solved: 1227
[Submit][Status][Discuss]

Description

BZOJ 3211: 花神游历各国/BZOJ 3038: 上帝造题的七分钟2 树状数组+并查集

Input

BZOJ 3211: 花神游历各国/BZOJ 3038: 上帝造题的七分钟2 树状数组+并查集

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


今天alone_wolf又在讲线段树啦

作为例题之一我查了题解。。。

因为对于每个数最多O(nloglogn)次不会再改变(变成0 or 1)

所以。。一顿乱搞

哦,对了,不要忘记最后一个数会指向区间之外,做一下标记要不会死循环。。。

PS: 3038比较坑。。看看题。。鬼畜WA两发


#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return x*f;
}
const int N=100100;
int n,fa[N];
ll c[N],a[N];
inline int find(int x)
{
	int t=x;
	while(t!=fa[t])t=fa[t];
	while(x!=fa[x])x=fa[x],fa[x]=t;
	return x;
}
inline void update(int x,ll val)
{for(;x<=n;x+=(x&-x))c[x]+=val;}
inline void modify(int x,int y)
{
	for(int i=x;i<=y;i=find(i+1))
	{
		ll t=floor(sqrt(a[i]));
		update(i,t-a[i]);a[i]=t;
		if(a[i]<=1)fa[i]=find(i+1);
	}
}
inline void query(int x,int y)
{
	ll sum=0;
	for(;y;y-=(y&-y))sum+=c[y];
	for(;x;x-=(x&-x))sum-=c[x];
	printf("%lld\n",sum);
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++){a[i]=read(),fa[i]=i,update(i,a[i]);if(a[i]<=1)fa[i]=i+1;}fa[n+1]=n+1;
	int m=read();
	while(m--)
	{
		int opt=read(),x=read(),y=read();if(x>y)swap(x,y);
		if(opt==1){query(x-1,y);}
		else {modify(x,y);}
	}
	return 0;
}
/*
4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4

101
11
11
*/