零分求调
查看原帖
零分求调
401660
Piqllmxiu楼主2025/6/22 17:03

分块+树状数组

#include<bits/stdc++.h>
using namespace std;

inline long long read()
{
	long long x = 0;
	char ch = getchar();
	while(!isdigit(ch))
	{
		if(ch == 'Q' || ch == 'C')return ch;
		ch = getchar();
	}
	while(isdigit(ch))
	{
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	
	return x;
}

inline long long gcd(long long a , long long b)
{
	if(a < 0 || b < 0)return gcd(abs(a) , abs(b));
	return b > 0 ? gcd(b , a % b) : a; 
}

const int MAXN = 5e5 + 5;

long long n , m , l , r , d;

long long lowbit(long long x){return x & (-x);}

long long cl[MAXN];

inline void treadd(long long x , long long d)
{
	while(x <= n)
	{
		cl[x] += d;
		x += lowbit(x);
	}
}

inline long long trequery(long long x)
{
	long long res = 0;
	while(x)
	{
		res += cl[x];
		x -= lowbit(x);
	}
	
	return res;
}

long long block , num;

long long st[MAXN] , ed[MAXN];

long long pos[MAXN];

long long al[MAXN];

long long s;

long long bl[MAXN];

void build()
{
	block = sqrt(n);
	num = sqrt(n);
	if(n % block)num++;
	for(int i = 1;i <= num;i++)
	{
		st[i] = (i - 1) * block + 1;
		ed[i] = i * block;
	}
	ed[num] = n;
	for(int i = 1;i <= n;i++)pos[i] = (i - 1) / block + 1;
	
	long long p;
	
	for(int i = 1;i <= num;i++)
	{
		p = al[st[i]];
		for(int j = st[i] + 1;j <= ed[i];j++)
		{
			p = gcd(p , al[j]);
		}
		bl[i] = p;
	}
	
	return;
}

void Add(long long x , long long d)
{
	al[x] += d;
	long long p = pos[x];
	long long ans = al[st[p]];
//	cout << ans << endl;
	for(int i = st[p] + 1;i <= ed[p];i++)
	{
		ans = gcd(ans , al[i]);
//		cout << ans << endl; 
	}
	
	bl[p] = ans;
}

long long query(long long l , long long r)
{
	long long ans = 0;
	if(r - l + 1 <= block)
	{
		ans = al[l];
		for(int i = l + 1;i <= r;i++)
		{
			ans = gcd(ans , al[i]);
		}
		
		return ans;
	}
	long long p = pos[l] , q = pos[r];
	if(l != st[p])
	{
		ans = al[l++];
		while(l <= ed[p])ans = gcd(ans , al[l++]);
		p++;
	}
	if(r != ed[q])
	{
		if(!ans)ans = al[r--];
		while(r >= st[q])ans = gcd(ans , al[r--]);
		q--;
	}
	if(!ans)ans = bl[p];
	for(int i = p + 1;i <= q;i++)ans = gcd(ans , bl[i]);
	
	return ans;
}

long long sum , bgn;

int main()
{
	n = read();
	m = read();
	for(int i = 1;i <= n;i++)al[i] = read();
	bgn = al[1];
	for(int i = n;i >= 1;i--)al[i] -= al[i - 1];
	for(int i = n;i >= 1;i--)cl[i] = al[i];
	build();
	for(int i = 1;i <= m;i++)
	{
		s = read();
		if(s == 'Q')
		{
			l = read();
			r = read();
			sum = trequery(l);
			if(l != 1)sum += bgn;
			sum = gcd(sum , query(l + 1 , r));
			printf("%lld\n" , sum);
		}
		else
		{
			l = read();
			r = read();
			d = read();
			Add(l , d);
			treadd(l , d);
			if(r == n)continue;
			Add(r + 1 , -d);
			treadd(r + 1 , -d);
		}
	}
	
	return 0;
} 
2025/6/22 17:03
加载中...