4373: 算术天才⑨与等差数列

xiaoxiao2021-02-28  109

首先特判掉k=0和l=r的情况,那么剩下来的情况要成立必满足三个条件: ①区间内max-min=k*区间长,用线段树维护max和min就好了。 ②区间排序后差分,gcd==k。gcd也可以用线段树维护,即差分后,gcd=gcd(左儿子gcd,右儿子gcd)(注意gcd=0是须特判)。 ③区间内没有重复的值。对于每个权值开一个set,用于查询每个点的右边第一次出现和它相等的值的下标。线段树维护这些下标的min,如果查询时min大于r说明符合条件。 然而烧了一天也没搞出这题来。最后,**哥告诉我:“你被卡常了。放弃吧。” 我简直是来搞笑的。 代码: #pragma GCC optimize("O2") #include<cstdio> #include<cstring> #include<iostream> #include<vector> #include<algorithm> #include<set> #include<map> using namespace std; #define rep(i,j,k) for(i=j;i<=k;++i) #define per(i,j,k) for(i=j;i>=k;--i) #define G getchar() #define LL long long #define pll pair<int,int> #define mkp make_pair #define X first #define Y second const int N=300005; int n,a[N],pre[N],nxt[N],ans; set<int>st[N<<1];map<int,int>mp;int id; int Max[N<<2],Min[N<<2],Gcd[N<<2],Flg[N<<2],Nxt[N<<2]; int MAX,MIN,GCD,NXT; inline void read(int &x){ char ch=G;//int f=1; for(;ch>57||ch<48;ch=G);//if(ch==45)f=-1; for(x=0;ch>=48&&ch<=57;ch=G)x=x*10+ch-48; //x*=f; } void modify2(int x,int l,int r,int num){ if(l==r){ Nxt[num]=nxt[l];return; } int mid=l+r>>1; if(x>mid)modify2(x,mid+1,r,num<<1|1); else modify2(x,l,mid,num<<1); Nxt[num]=min(Nxt[num<<1],Nxt[num<<1|1]); } inline void ins(int i){ set<int>::iterator ii; if(mp.insert(mkp(a[i],id)).Y){ st[id].insert(nxt[i]=n+1);st[id].insert(pre[i]=0); st[id++].insert(i); } else{ ii=st[mp[a[i]]].insert(i).X; ++ii; if((nxt[i]=*ii)<=n)pre[nxt[i]]=i; --ii;--ii; if(pre[i]=*ii){nxt[pre[i]]=i;modify2(pre[i],1,n,1);} } } inline void del(int i){ int x=mp[a[i]]; set<int>::iterator ii=st[x].lower_bound(i); if(nxt[i]<=n)pre[nxt[i]]=pre[i]; if(pre[i]){nxt[pre[i]]=nxt[i];modify2(pre[i],1,n,1);} st[x].erase(ii); } int gcd(int x,int y){ if(!x)return y; if(!y)return x; if(x%y==0)return y; return gcd(y,x%y); } inline void up(int num){ Max[num]=max(Max[num<<1],Max[num<<1|1]); Min[num]=min(Min[num<<1],Min[num<<1|1]); Flg[num]=Flg[num<<1]==Flg[num<<1|1]?Flg[num<<1]:-1; Nxt[num]=min(Nxt[num<<1],Nxt[num<<1|1]); } inline void up2(int num){ Gcd[num]=gcd(Gcd[num<<1],Gcd[num<<1|1]); } void build(int l,int r,int num){ if(l==r){ Max[num]=Min[num]=Flg[num]=a[l]; Nxt[num]=nxt[l];return; } int mid=l+r>>1; build(l,mid,num<<1);build(mid+1,r,num<<1|1); up(num); } void build2(int l,int r,int num){ if(l==r){ Gcd[num]=abs(a[l]-a[l+1]); return; } int mid=l+r>>1; build2(l,mid,num<<1);build2(mid+1,r,num<<1|1); up2(num); } void modify(int x,int y,int l,int r,int num){ if(l==r){ del(l); Max[num]=Min[num]=Flg[num]=a[l]=y; ins(l);Nxt[num]=nxt[l];return; } int mid=l+r>>1; if(x<=mid)modify(x,y,l,mid,num<<1); else modify(x,y,mid+1,r,num<<1|1); up(num); } void modify2(int x,int y,int l,int r,int num){ if(l==r){ Gcd[num]=y;return; } int mid=l+r>>1; if(x<=mid)modify2(x,y,l,mid,num<<1); else modify2(x,y,mid+1,r,num<<1|1); up2(num); } int query1(int L,int R,int l,int r,int num){ if(L<=l&&r<=R)return Flg[num]; int mid=l+r>>1; if(R<=mid)return query1(L,R,l,mid,num<<1); if(L>mid)return query1(L,R,mid+1,r,num<<1|1); int tmp=query1(L,R,l,mid,num<<1); return tmp==query1(L,R,mid+1,r,num<<1|1)?tmp:-1; } int query2(int L,int R,int l,int r,int num){ if(L<=l&&r<=R){ MAX=max(MAX,Max[num]); MIN=min(MIN,Min[num]); NXT=min(NXT,Nxt[num]); return Gcd[num]; } int mid=l+r>>1; if(R<=mid)return query2(L,R,l,mid,num<<1); if(L>mid)return query2(L,R,mid+1,r,num<<1|1); return gcd(query2(L,R,l,mid,num<<1),query2(L,R,mid+1,r,num<<1|1)); } void query(int L,int R,int l,int r,int num){ if(L<=l&&r<=R){ MAX=max(MAX,Max[num]); MIN=min(MIN,Min[num]); NXT=min(NXT,Nxt[num]); return; } int mid=l+r>>1; if(L<=mid)query(L,R,l,mid,num<<1); if(R>mid)query(L,R,mid+1,r,num<<1|1); } int main(){ // freopen("r.in","r",stdin); // freopen("w.out","w",stdout); int Q,i,o,x,y,k; read(n);read(Q); rep(i,1,n){ read(a[i]); if(n!=1)ins(i); } if(n!=1)build(1,n,1),build2(1,n-1,1); while(Q--){ read(o);read(x);read(y);x^=ans;y^=ans; if(o==1){ if(n==1)continue; if(x<n)modify2(x,abs(a[x+1]-y),1,n-1,1); if(x>1)modify2(x-1,abs(a[x-1]-y),1,n-1,1); modify(x,y,1,n,1); } else{ read(k);k^=ans; if(x==y){ ++ans,puts("Yes");continue; } if(!k){ if(query1(x,y,1,n,1)>=0) ++ans,puts("Yes"); else puts("No"); continue; } MAX=0,MIN=NXT=n+1; query(x,y,1,n,1); GCD=query2(x,y-1,1,n-1,1); if(GCD==k&&MAX-MIN==k*(y-x)&&NXT>y) ++ans,puts("Yes"); else puts("No"); } } return 0; }
转载请注明原文地址: https://www.6miu.com/read-96892.html

最新回复(0)