BZOJ4373: 算术天才⑨与等差数列
题解: 很显然这个题 等差数列没有办法维护 那么我们考虑一段区间为等差数列 那么应该满足
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

浙公网安备 33010602011771号