[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 }

 

posted @ 2018-11-05 15:15  HocRiser  阅读(212)  评论(0编辑  收藏  举报