#线段树#洛谷 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