题解: 很显然这个题 等差数列没有办法维护 那么我们考虑一段区间为等差数列 那么应该满足
1.最大值和最小值的差等于(r-l)*k
2.任意相邻差值的绝对值的gcd与k的gcd等于k
3.特判k==0的情况
3.用set去重
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=3e5+10; const double eps=1e-8; const int inf=1e9+7; #define ll long long using namespace std; // struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; // void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } int Gcd[MAXN<<2],pre[MAXN<<2],minn[MAXN<<2],maxx[MAXN<<2],vis[MAXN],a[MAXN],b[MAXN]; int cnt,tot; map<int,int>ma; map<int,int>::iterator ite; set<int>s[MAXN<<1]; set<int>::iterator ip,id; void up(int x){ Gcd[x]=__gcd(Gcd[x<<1],Gcd[x<<1|1]); pre[x]=max(pre[x<<1],pre[x<<1|1]); minn[x]=min(minn[x<<1],minn[x<<1|1]); maxx[x]=max(maxx[x<<1],maxx[x<<1|1]); } void built(int rt,int l,int r){ if(l==r){Gcd[rt]=b[l];minn[rt]=maxx[rt]=a[l];pre[rt]=vis[l];return ;} int mid=(l+r)>>1; built(rt<<1,l,mid); built(rt<<1|1,mid+1,r); up(rt); } void update1(int rt,int l,int r,int t,int vul){ if(l==r){pre[rt]=vul;return ;} int mid=(l+r)>>1; if(t<=mid)update1(rt<<1,l,mid,t,vul); else update1(rt<<1|1,mid+1,r,t,vul); pre[rt]=max(pre[rt<<1],pre[rt<<1|1]); } void update2(int rt,int l,int r,int t,int vul){ if(l==r){Gcd[rt]=abs(vul-a[l-1]);minn[rt]=maxx[rt]=vul;return ;} int mid=(l+r)>>1; if(t<=mid)update2(rt<<1,l,mid,t,vul); else update2(rt<<1|1,mid+1,r,t,vul); up(rt); } void update3(int rt,int l,int r,int t,int vul){ if(l==r){Gcd[rt]=abs(vul-a[l]);return ;} int mid=(l+r)>>1; if(t<=mid)update3(rt<<1,l,mid,t,vul); else update3(rt<<1|1,mid+1,r,t,vul); up(rt); } int ans; void querty1(int rt,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ans=__gcd(ans,Gcd[rt]);return ;} int mid=(l+r)>>1; if(ql<=mid)querty1(rt<<1,l,mid,ql,qr); if(qr>mid)querty1(rt<<1|1,mid+1,r,ql,qr); } int ans1,ans2,ans3; void querty2(int rt,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ans1=min(ans1,minn[rt]);ans2=max(ans2,maxx[rt]);ans3=max(ans3,pre[rt]);return ;} int mid=(l+r)>>1; if(ql<=mid)querty2(rt<<1,l,mid,ql,qr); if(qr>mid)querty2(rt<<1|1,mid+1,r,ql,qr); } int main(){ int n,m;n=read();m=read();cnt=tot=0; inc(i,1,n){ a[i]=read(); if(ma.find(a[i])==ma.end())ma[a[i]]=++cnt,s[cnt].insert(i),vis[i]=0; else{ ite=ma.find(a[i]); ip=s[ite->second].lower_bound(i);ip--;vis[i]=(*ip);s[ite->second].insert(i); } b[i]=abs(a[i]-a[i-1]); //cout<<b[i]<<" "; } //cout<<endl; built(1,1,n);int op,l,r,k; inc(i,1,m){ op=read();l=read();r=read();l^=tot;r^=tot; if(op==1){ update2(1,1,n,l,r); if(l!=n)update3(1,1,n,l+1,r); ite=ma.find(a[l]);ip=s[ite->second].lower_bound(l+1);id=s[ite->second].lower_bound(l); if(ip!=s[ite->second].end()){ if(id==s[ite->second].begin())update1(1,1,n,(*ip),0),s[ite->second].erase(id); else { int t=(*ip);ip=id;id--; update1(1,1,n,t,(*id));s[ite->second].erase(ip); } } ite=ma.find(r); if(ite==ma.end())ma[r]=++cnt,s[cnt].insert(l),update1(1,1,n,l,0); else{ ip=s[ite->second].lower_bound(l); if(ip!=s[ite->second].end()){update1(1,1,n,(*ip),l);} if(ip==s[ite->second].begin()){update1(1,1,n,l,0);} else ip--,update1(1,1,n,l,(*ip)); s[ite->second].insert(l); } a[l]=r; } else{ //cout<<i<<"::::"<<op<<" "<<l<<" "<<r<<endl; k=read();k^=tot; if(l==r){tot++;puts("Yes");continue;} //k^=tot; ans=0;querty1(1,1,n,l+1,r); ans1=inf;ans2=ans3=0;querty2(1,1,n,l,r); //cout<<i<<" "<<k<<"===="<<ans1<<" "<<ans2<<" "<<ans<<endl; if(k==0&&ans1==ans2){tot++;puts("Yes");continue;} else if(k==0&&ans1!=ans2){puts("No");continue;} if(__gcd(ans,k)!=k){puts("No");continue;} int t=(ans2-ans1)%k;int t1=(ans2-ans1)/k; //cout<<t<<" "<<t1<<" "<<i<<endl; if(ans3<l&&t==0&&t1==r-l){tot++;puts("Yes");continue;} else puts("No"); } } return 0; }
4373: 算术天才⑨与等差数列
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2092 Solved: 510
[Submit][Status][Discuss]
Description
算术天才⑨非常喜欢和等差数列玩耍。
有一天,他给了你一个长度为n的序列,其中第i个数为a[i]。
他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序后能否形成公差为k的等差数列。
当然,他还会不断修改其中的某一项。
为了不被他鄙视,你必须要快速并正确地回答完所有问题。
注意:只有一个数的数列也是等差数列。
Input
第一行包含两个正整数n,m(1<=n,m<=300000),分别表示序列的长度和操作的次数。
第二行包含n个整数,依次表示序列中的每个数a[i](0<=a[i]<=10^9)。
接下来m行,每行一开始为一个数op,
若op=1,则接下来两个整数x,y(1<=x<=n,0<=y<=10^9),表示把a[x]修改为y。
若op=2,则接下来三个整数l,r,k(1<=l<=r<=n,0<=k<=10^9),表示一个询问。
在本题中,x,y,l,r,k都是经过加密的,都需要异或你之前输出的Yes的个数来进行解密。
Output
输出若干行,对于每个询问,如果可以形成等差数列,那么输出Yes,否则输出No。
Sample Input
5 3
1 3 2 5 6
2 1 5 1
1 5 4
2 1 5 1
1 3 2 5 6
2 1 5 1
1 5 4
2 1 5 1
Sample Output
No
Yes
Yes