[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的情况。

 #include<set>
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls (x<<1)
#define rs (ls|1)
#define lson ls,L,mid
#define rson rs,mid+1,R
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
using namespace std; const int N=;
int n,m,tot,op,x,y,l,r,k,w,a[N],d[N],pre[N],Gcd[N<<],mn[N<<],mx[N<<],mxp[N<<];
set<int>S[N<<];
map<int,int>mp; int gcd(int a,int b){ return b ? gcd(b,a%b) : a; } void upd(int x){
mn[x]=min(mn[ls],mn[rs]); mx[x]=max(mx[ls],mx[rs]);
Gcd[x]=gcd(Gcd[ls],Gcd[rs]); mxp[x]=max(mxp[ls],mxp[rs]);
} void build(int x,int L,int R){
if (L==R){ Gcd[x]=d[L]; mn[x]=mx[x]=a[L]; mxp[x]=pre[L]; return; }
int mid=(L+R)>>;
build(lson); build(rson); upd(x);
} void mdf(int x,int L,int R,int pos,int k,int op){
if (L==R){
if (op==) Gcd[x]=k;
if (op==) mn[x]=mx[x]=k;
if (op==) mxp[x]=k;
return;
}
int mid=(L+R)>>;
if (pos<=mid) mdf(lson,pos,k,op); else mdf(rson,pos,k,op);
upd(x);
} int que(int x,int L,int R,int l,int r,int op){
if (L==l && r==R){
if (op==) return Gcd[x];
if (op==) return mn[x];
if (op==) return mx[x];
if (op==) return mxp[x];
}
int mid=(L+R)>>;
if (r<=mid) return que(lson,l,r,op);
else if (l>mid) return que(rson,l,r,op);
else{
if (op==) return gcd(que(lson,l,mid,op),que(rson,mid+,r,op));
if (op==) return min(que(lson,l,mid,op),que(rson,mid+,r,op));
if (op==) return max(que(lson,l,mid,op),que(rson,mid+,r,op));
if (op==) return max(que(lson,l,mid,op),que(rson,mid+,r,op));
}
return ;
} int main(){
freopen("bzoj4373.in","r",stdin);
freopen("bzoj4373.out","w",stdout);
scanf("%d%d",&n,&m);
rep(i,,n){
scanf("%d",&a[i]),d[i]=abs(a[i]-a[i-]);
if (!mp.count(a[i])){
mp[a[i]]=++tot; pre[i]=; S[tot].insert(i);
}else{
int t=mp[a[i]]; pre[i]=*(--S[t].end()); S[t].insert(i);
}
}
build(,,n);
rep(i,,m){
scanf("%d",&op);
if (op==){
scanf("%d%d",&x,&y); x^=w; y^=w;
if (y==a[x]) continue;
d[x]=abs(y-a[x-]); mdf(,,n,x,d[x],);
if (x<n) d[x+]=abs(a[x+]-y),mdf(,,n,x+,d[x+],);
int t=mp[a[x]]; set<int>::iterator it=S[t].upper_bound(x);
if (it!=S[t].end()) pre[*it]=pre[x],mdf(,,n,*it,pre[*it],); S[t].erase(x);
a[x]=y; mdf(,,n,x,a[x],);
if (!mp.count(a[x])){
mp[a[x]]=++tot; pre[x]=; S[tot].insert(x); mdf(,,n,x,pre[x],);
}else{
int t=mp[a[x]];
set<int>::iterator it=S[t].insert(x).first;
if (it==S[t].begin()) pre[x]=; else pre[x]=*(--it);
mdf(,,n,x,pre[x],);
it=S[t].upper_bound(x);
if (it!=S[t].end()) pre[*it]=x,mdf(,,n,*it,pre[*it],);
}
}else{
scanf("%d%d%d",&l,&r,&k); l^=w; r^=w; k^=w;
if (l==r){ w++; puts("Yes"); continue; }
if (!k){
if (que(,,n,l,r,)==que(,,n,l,r,)) w++,puts("Yes"); else puts("No");
continue;
}
if (que(,,n,l,r,)-que(,,n,l,r,)!=1ll*k*(r-l) || que(,,n,l+,r,)%k || que(,,n,l,r,)>=l) puts("No");
else w++,puts("Yes");
}
}
return ;
}
上一篇:获取不到jdbc.driver的值解决办法


下一篇:公司内部培训AlwaysOn PPT分享