luogu P5278 算术天才⑨与等差数列
题面传送门
hash那个很屑我们不去管。考虑确定性算法。
首先我们要保证区间最大减去最小为\((r-l)k\)
然后如果\(k=0\)直接看\(gcd\)即可。
否则看\(gcd\)是不是\(k\)的倍数且区间没有重复的数显然是对的。
然后关于区间没有重复的数直接维护前驱即可。
时间复杂度\(O(nlogn)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 300000
#define M 30
#define mod 1000000007
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,x,y,z,A[N+5],op,flag,Lastans,Maxn,Minn,now;
struct Min_Max_Tree{
int Maxn[N+5<<2],Minn[N+5<<2],A[N+5];
I void Up(int x){Maxn[x]=max(Maxn[x<<1],Maxn[x<<1|1]);Minn[x]=min(Minn[x<<1],Minn[x<<1|1]);}
I void build(int l=1,int r=n,int now=1){if(l==r)return (void)(Maxn[now]=Minn[now]=A[l]);int m=l+r>>1;build(l,m,now<<1);build(m+1,r,now<<1|1);Up(now);}
I void change(int x,int y,int l=1,int r=n,int now=1){
if(l==r) return (void)(Maxn[now]=Minn[now]=y);int m=l+r>>1;x<=m?change(x,y,l,m,now<<1):change(x,y,m+1,r,now<<1|1);Up(now);
}
I int find_Max(int x,int y,int l=1,int r=n,int now=1){
if(x<=l&&r<=y) return Maxn[now];int m=l+r>>1,ans1=0,ans2=0;x<=m&&(ans1=find_Max(x,y,l,m,now<<1));y>m&&(ans2=find_Max(x,y,m+1,r,now<<1|1));return max(ans1,ans2);
}
I int find_Min(int x,int y,int l=1,int r=n,int now=1){
if(x<=l&&r<=y) return Minn[now];int m=l+r>>1,ans1=2e9,ans2=2e9;x<=m&&(ans1=find_Min(x,y,l,m,now<<1));y>m&&(ans2=find_Min(x,y,m+1,r,now<<1|1));return min(ans1,ans2);
}
}S1;
struct Col_Tree{
int A[N+5],F[N+5<<2],cnt;set<int> G[N+5<<1];set<int>::it now,pus;map<int,int> Fs;
I void Make(int &x){!Fs[x]&&(Fs[x]=++cnt);x=Fs[x];}
I void Up(int x){F[x]=max(F[x<<1],F[x<<1|1]);}
I void get(int x,int y,int l=1,int r=n,int now=1){
if(l==r) return (void)(F[now]=y);int m=l+r>>1;x<=m?get(x,y,l,m,now<<1):get(x,y,m+1,r,now<<1|1);Up(now);
}
I int find(int x,int y,int l=1,int r=n,int now=1){
if(x<=l&&r<=y) return F[now];int m=l+r>>1,ans1=0,ans2=0;x<=m&&(ans1=find(x,y,l,m,now<<1));y>m&&(ans2=find(x,y,m+1,r,now<<1|1));return max(ans1,ans2);
}
I void build(){
re int i;for(i=1;i<=n;i++)Make(A[i]),now=G[A[i]].end(),(now!=G[A[i]].begin())&&(get(i,*(--now)),0),G[A[i]].insert(i);
}
I void change(int x,int y){
Make(y);now=pus=G[A[x]].lower_bound(x);pus++;if(pus!=G[A[x]].end()) get(*pus,((--now)==G[A[x]].begin())?0:*now);
G[A[x]].erase(x);A[x]=y;G[A[x]].insert(x);now=pus=G[A[x]].lower_bound(x);get(x,(now!=G[A[x]].begin())?*(--now):0);++pus;if(pus!=G[A[x]].end()) get(*pus,x);
}
I int GetAns(int x,int y){return x>find(x,y);}
}S2;
struct Gcd_Tree{
int A[N+5],F[N+5<<2];
I void Up(int x){F[x]=__gcd(F[x<<1],F[x<<1|1]);}
I void build(int l=1,int r=n-1,int now=1){
if(l==r) return (void)(F[now]=A[l+1]-A[l]);int m=l+r>>1;build(l,m,now<<1);build(m+1,r,now<<1|1);Up(now);
}
I void get(int x,int y,int l=1,int r=n-1,int now=1){
if(l==r) return (void)(F[now]=y);int m=l+r>>1;x<=m?get(x,y,l,m,now<<1):get(x,y,m+1,r,now<<1|1);Up(now);
}
I void change(int x,int y){A[x]=y;x&&(get(x-1,A[x]-A[x-1]),0);x^n&&(get(x,A[x+1]-A[x]),0);}
I int find(int x,int y,int l=1,int r=n-1,int now=1){
if(x<=l&&r<=y) return F[now];int m=l+r>>1,ans=0;x<=m&&(ans=__gcd(ans,find(x,y,l,m,now<<1)));y>m&&(ans=__gcd(ans,find(x,y,m+1,r,now<<1|1)));return ans;
}
}S3;
int main(){
freopen("1.in","r",stdin);freopen("1.out","w",stdout);
re int i;scanf("%d%d",&n,&m);for(i=1;i<=n;i++) scanf("%d",&A[i]),S1.A[i]=S2.A[i]=S3.A[i]=A[i];S1.build();S2.build();S3.build();
while(m--) {
scanf("%d",&op);if(op==1) scanf("%d%d",&x,&y),x^=Lastans,y^=Lastans,S1.change(x,y),S2.change(x,y),S3.change(x,y);
else{
scanf("%d%d%d",&x,&y,&z),x^=Lastans,y^=Lastans,z^=Lastans;if(x==y) {Lastans++;printf("Yes\n");continue;}
Maxn=S1.find_Max(x,y),Minn=S1.find_Min(x,y);/*printf("%d %d\n",Maxn,Minn);*/if(Maxn-Minn!=(y-x)*z){printf("No\n");continue;}
if(!z){if(!S3.find(x,y-1)) printf("Yes\n"),Lastans++;else printf("No\n");continue;}//printf("%d %d %d %d ",x,y,z,S2.find(x,y));
/*printf("%d %d\n",S3.find(x,y),S2.find(x,y));*/if(S3.find(x,y-1)%z||!S2.GetAns(x,y))printf("No\n");else Lastans++,printf("Yes\n");
}
}
}