把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

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");
		} 
	}
}
posted @ 2021-07-10 22:19  275307894a  阅读(49)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end