[BZOJ5028]小Z的加油店

[BZOJ5028]小Z的加油店

题目大意:

一个长度为\(n(n\le10^5)\)的数列,\(m(m\le10^5)\)次操作,支持区间加和区间\(\gcd\)

思路:

线段树维护差分,\(\gcd(A_l,\cdots,A_r)\)就是区间\([l,r]\)差分的\(\gcd\)\(A_r\)\(\gcd\)

源代码:

#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
const int N=1e5+1;
int a[N];
class SegmentTree {
	#define _left <<1
	#define _right <<1|1
	#define mid ((b+e)>>1)
	private:
		int gcd[N<<2],sum[N<<2];
		void push_up(const int &p) {
			gcd[p]=std::__gcd(gcd[p _left],gcd[p _right]);
			sum[p]=sum[p _left]+sum[p _right];
		}
	public:
		void build(const int &p,const int &b,const int &e) {
			if(b==e) {
				gcd[p]=sum[p]=a[b];
				return;
			}
			build(p _left,b,mid);
			build(p _right,mid+1,e);
			push_up(p);
		}
		void modify(const int &p,const int &b,const int &e,const int &x,const int &y) {
			if(b==e) {
				gcd[p]+=y;
				sum[p]+=y;
				return;
			}
			if(x<=mid) modify(p _left,b,mid,x,y);
			if(x>mid) modify(p _right,mid+1,e,x,y);
			push_up(p);
		}
		int query_gcd(const int &p,const int &b,const int &e,const int &l,const int &r) const {
			if(b==l&&e==r) return gcd[p];
			if(r<=mid) return query_gcd(p _left,b,mid,l,r);
			if(l>mid) return query_gcd(p _right,mid+1,e,l,r);
			return std::__gcd(query_gcd(p _left,b,mid,l,mid),query_gcd(p _right,mid+1,e,mid+1,r));
		}
		int query_sum(const int &p,const int &b,const int &e,const int &x) const {
			if(e==x) return sum[p];
			if(x<=mid) return query_sum(p _left,b,mid,x);
			if(x>mid) return sum[p _left]+query_sum(p _right,mid+1,e,x);
		}
	#undef _left
	#undef _right
	#undef mid
};
SegmentTree t;
int main() {
	const int n=getint(),m=getint();
	for(register int i=1;i<=n;i++) a[i]=getint();
	for(register int i=n;i>=1;i--) a[i]-=a[i-1];
	t.build(1,1,n);
	for(register int i=0;i<m;i++) {
		const int opt=getint(),l=getint(),r=getint();
		if(opt==1) {
			if(l<r) {
				printf("%d\n",std::abs(std::__gcd(t.query_sum(1,1,n,r),t.query_gcd(1,1,n,l+1,r))));
			} else {
				printf("%d\n",t.query_sum(1,1,n,r));
			}
		} else {
			const int v=getint();
			t.modify(1,1,n,l,v);
			if(r<n) t.modify(1,1,n,r+1,-v);
		}
	}
	return 0;
}
posted @ 2018-07-21 13:03  skylee03  阅读(304)  评论(0编辑  收藏  举报