[BZOJ4373]算术天才⑨与等差数列(线段树)
[l,r]中所有数排序后能构成公差为k的等差数列,当且仅当:
1.区间中最大数-最小数=k*(r-l)
2.k能整除区间中任意两个相邻数之差,即k | gcd(a[l+1]-a[l],a[l+2]-a[l+1],...,a[r]-a[r-1])
3.区间中任意两个数不相同,即设pre[i]为序列中i之前第一个与a[i]相等的数的位置,则max(pre[l],...,pre[r])<l
于是线段树分别维护:区间最大值,区间最小值,区间相邻差的gcd,区间pre的最大值即可。
注意特判下l=r和k=0的情况。
1 #include<set> 2 #include<map> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #define ls (x<<1) 7 #define rs (ls|1) 8 #define lson ls,L,mid 9 #define rson rs,mid+1,R 10 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 11 using namespace std; 12 13 const int N=300010; 14 int n,m,tot,op,x,y,l,r,k,w,a[N],d[N],pre[N],Gcd[N<<2],mn[N<<2],mx[N<<2],mxp[N<<2]; 15 set<int>S[N<<1]; 16 map<int,int>mp; 17 18 int gcd(int a,int b){ return b ? gcd(b,a%b) : a; } 19 20 void upd(int x){ 21 mn[x]=min(mn[ls],mn[rs]); mx[x]=max(mx[ls],mx[rs]); 22 Gcd[x]=gcd(Gcd[ls],Gcd[rs]); mxp[x]=max(mxp[ls],mxp[rs]); 23 } 24 25 void build(int x,int L,int R){ 26 if (L==R){ Gcd[x]=d[L]; mn[x]=mx[x]=a[L]; mxp[x]=pre[L]; return; } 27 int mid=(L+R)>>1; 28 build(lson); build(rson); upd(x); 29 } 30 31 void mdf(int x,int L,int R,int pos,int k,int op){ 32 if (L==R){ 33 if (op==0) Gcd[x]=k; 34 if (op==1) mn[x]=mx[x]=k; 35 if (op==2) mxp[x]=k; 36 return; 37 } 38 int mid=(L+R)>>1; 39 if (pos<=mid) mdf(lson,pos,k,op); else mdf(rson,pos,k,op); 40 upd(x); 41 } 42 43 int que(int x,int L,int R,int l,int r,int op){ 44 if (L==l && r==R){ 45 if (op==0) return Gcd[x]; 46 if (op==1) return mn[x]; 47 if (op==2) return mx[x]; 48 if (op==3) return mxp[x]; 49 } 50 int mid=(L+R)>>1; 51 if (r<=mid) return que(lson,l,r,op); 52 else if (l>mid) return que(rson,l,r,op); 53 else{ 54 if (op==0) return gcd(que(lson,l,mid,op),que(rson,mid+1,r,op)); 55 if (op==1) return min(que(lson,l,mid,op),que(rson,mid+1,r,op)); 56 if (op==2) return max(que(lson,l,mid,op),que(rson,mid+1,r,op)); 57 if (op==3) return max(que(lson,l,mid,op),que(rson,mid+1,r,op)); 58 } 59 return 0; 60 } 61 62 int main(){ 63 freopen("bzoj4373.in","r",stdin); 64 freopen("bzoj4373.out","w",stdout); 65 scanf("%d%d",&n,&m); 66 rep(i,1,n){ 67 scanf("%d",&a[i]),d[i]=abs(a[i]-a[i-1]); 68 if (!mp.count(a[i])){ 69 mp[a[i]]=++tot; pre[i]=0; S[tot].insert(i); 70 }else{ 71 int t=mp[a[i]]; pre[i]=*(--S[t].end()); S[t].insert(i); 72 } 73 } 74 build(1,1,n); 75 rep(i,1,m){ 76 scanf("%d",&op); 77 if (op==1){ 78 scanf("%d%d",&x,&y); x^=w; y^=w; 79 if (y==a[x]) continue; 80 d[x]=abs(y-a[x-1]); mdf(1,1,n,x,d[x],0); 81 if (x<n) d[x+1]=abs(a[x+1]-y),mdf(1,1,n,x+1,d[x+1],0); 82 int t=mp[a[x]]; set<int>::iterator it=S[t].upper_bound(x); 83 if (it!=S[t].end()) pre[*it]=pre[x],mdf(1,1,n,*it,pre[*it],2); S[t].erase(x); 84 a[x]=y; mdf(1,1,n,x,a[x],1); 85 if (!mp.count(a[x])){ 86 mp[a[x]]=++tot; pre[x]=0; S[tot].insert(x); mdf(1,1,n,x,pre[x],2); 87 }else{ 88 int t=mp[a[x]]; 89 set<int>::iterator it=S[t].insert(x).first; 90 if (it==S[t].begin()) pre[x]=0; else pre[x]=*(--it); 91 mdf(1,1,n,x,pre[x],2); 92 it=S[t].upper_bound(x); 93 if (it!=S[t].end()) pre[*it]=x,mdf(1,1,n,*it,pre[*it],2); 94 } 95 }else{ 96 scanf("%d%d%d",&l,&r,&k); l^=w; r^=w; k^=w; 97 if (l==r){ w++; puts("Yes"); continue; } 98 if (!k){ 99 if (que(1,1,n,l,r,2)==que(1,1,n,l,r,1)) w++,puts("Yes"); else puts("No"); 100 continue; 101 } 102 if (que(1,1,n,l,r,2)-que(1,1,n,l,r,1)!=1ll*k*(r-l) || que(1,1,n,l+1,r,0)%k || que(1,1,n,l,r,3)>=l) puts("No"); 103 else w++,puts("Yes"); 104 } 105 } 106 return 0; 107 }