其他分享
首页 > 其他分享> > #线段树#洛谷 5278 算术天才⑨与等差数列

#线段树#洛谷 5278 算术天才⑨与等差数列

作者:互联网

题目传送门


分析

判断一个等差数列需要三个条件,首项末项和公差。

转化一下就是最大值减去最小值是公差的长度减一倍。

并且除非公差为零否则互不相同,相邻两个位置的差的最大公约数为公差。

把这三个条件在线段树上维护并判断即可。


代码

#include <cstdio>
#include <cctype>
#include <map>
#include <set>
using namespace std;
const int N=300011; map<int,int>uk;
set<int>K[N<<1]; set<int>::iterator it;
int w[N<<2],mn[N<<2],mx[N<<2],Mx[N<<2],a[N],tot,pre[N],n,m,_mx,_mn,_Mx;
int iut(){
	int ans=0,f=1; char c=getchar();
	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans*f;
}
int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;}
int Abs(int x){return x<0?-x:x;}
int gcd(int x,int y){return y?gcd(y,x%y):x;}
void pup(int k){
	w[k]=gcd(w[k<<1],w[k<<1|1]);
	mn[k]=min(mn[k<<1],mn[k<<1|1]);
	mx[k]=max(mx[k<<1],mx[k<<1|1]);
	Mx[k]=max(Mx[k<<1],Mx[k<<1|1]);
}
void build(int k,int l,int r){
	if (l==r){
		w[k]=Abs(a[l]-a[l+1]);
		Mx[k]=pre[l],mx[k]=mn[k]=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
    pup(k);
}
void update(int k,int l,int r,int x){
	if (l==r){
		w[k]=Abs(a[l]-a[l+1]);
		Mx[k]=pre[l],mx[k]=mn[k]=a[l];
		return;
	}
	int mid=(l+r)>>1;
	if (x<=mid) update(k<<1,l,mid,x);
	    else update(k<<1|1,mid+1,r,x);
	pup(k);
}
void update0(int k,int l,int r,int x,int y){
	if (l==r){
		Mx[k]=y;
		return;
	}
	int mid=(l+r)>>1;
	if (x<=mid) update0(k<<1,l,mid,x,y);
	    else update0(k<<1|1,mid+1,r,x,y);
	Mx[k]=max(Mx[k<<1],Mx[k<<1|1]);
}
void update1(int k,int l,int r,int x,int y){
	if (l==r){
		w[k]=Abs(y);
		return;
	}
	int mid=(l+r)>>1;
	if (x<=mid) update1(k<<1,l,mid,x,y);
	    else update1(k<<1|1,mid+1,r,x,y);
	w[k]=gcd(w[k<<1],w[k<<1|1]); 
}
int query_gcd(int k,int l,int r,int x,int y){
	if (l==x&&r==y) return w[k];
	int mid=(l+r)>>1;
	if (y<=mid) return query_gcd(k<<1,l,mid,x,y);
	else if (x>mid) return query_gcd(k<<1|1,mid+1,r,x,y);
	    else return gcd(query_gcd(k<<1,l,mid,x,mid),query_gcd(k<<1|1,mid+1,r,mid+1,y));
}
void query(int k,int l,int r,int x,int y){
	if (l==x&&r==y){
		_Mx=max(_Mx,Mx[k]);
		_mx=max(_mx,mx[k]);
		_mn=min(_mn,mn[k]);
		return;
	}
	int mid=(l+r)>>1;
	if (y<=mid) query(k<<1,l,mid,x,y);
	else if (x>mid) query(k<<1|1,mid+1,r,x,y);
	    else query(k<<1,l,mid,x,mid),query(k<<1|1,mid+1,r,mid+1,y);
}
int main(){
	n=iut(); m=iut();
	for (int i=1,t;i<=n;++i){
		a[i]=iut();
		if (!uk[a[i]]){
			uk[a[i]]=t=++tot;
			K[tot].insert(0);
		}else t=uk[a[i]];
		it=--K[t].upper_bound(i);
		pre[i]=*it,K[t].insert(i);
	}
	build(1,1,n);
	for (int i=1,lans=0,t;i<=m;++i){
		int opt=iut(),x=iut()^lans,y=iut()^lans;
		if (opt==1){
			if (a[x]==y) continue; t=uk[a[x]];
			K[t].erase(x);
			it=K[t].upper_bound(x);
		    if (it!=K[t].end()){
		    	int now=*it;
		    	update0(1,1,n,now,pre[now]=*(--it));
			}
			if (x>1) update1(1,1,n,x-1,a[x-1]-y);
			if (!uk[y]){
				uk[y]=t=++tot,K[tot].insert(pre[x]=0);
			}else{
				t=uk[y];
				it=K[t].upper_bound(x);
				if (it!=K[t].end()){
					int now=*it;
					update0(1,1,n,now,pre[now]=x);
				}
				pre[x]=*(--it);
			}
			K[t].insert(x),a[x]=y;
			update(1,1,n,x);
		}else{
			int z=iut()^lans;
			if (x==y){
				++lans,puts("Yes");
				continue;
			} 
			_Mx=_mx=0,_mn=0x3f3f3f3f,query(1,1,n,x,y);
			if ((_Mx>=x&&z)||_mx-_mn!=1ll*(y-x)*z) {puts("No"); continue;}
			if (query_gcd(1,1,n,x,y-1)==z) ++lans,puts("Yes");
			    else puts("No");
		}
	}
	return 0;
}

标签:pre,洛谷,puts,int,5278,公差,query,include,等差数列
来源: https://www.cnblogs.com/Spare-No-Effort/p/16053041.html