设$pre[i]$表示第$i$个数上一次出现的位置,$d[i]=abs(a[i]-a[i+1])$。

用线段树维护区间内$a$的最小值、最大值,$pre$的最大值以及$d$的$\gcd$。

对于询问$l\ r\ k$,首先特判掉$l=r$或者$k=0$的情况。

然后求出区间最小值和最大值、以及$pre$的最大值,判断最值是否合法以及$pre$是否都小于$l$。

如果都满足,那么继续查询$[l,r-1]$里所有$d$的$\gcd$,如果$\gcd$是$k$的倍数,那么就可行。

时间复杂度$O(n\log n)$。

#include<cstdio>
#include<cstdlib>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int N=300010,M=1050000;
int n,m,cnt,i,op,x,y,z,a[N],b[N],c[N],d[N],K;
int vmi[M],vma[M],vp[M],vd[M],mi,ma,flag,g;
map<int,int>id;
set<int>T[N<<1];
set<int>::iterator pre,nxt;
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline int abs(int x){return x>0?x:-x;}
inline int gcd(int a,int b){
if(!a)return b;
if(!b)return a;
return __gcd(a,b);
}
inline int getid(int x){
int&t=id[x];
if(t)return t;
t=++cnt;
T[t].insert(0),T[t].insert(n+1);
return t;
}
void build(int x,int a,int b){
if(a==b){
vmi[x]=vma[x]=::a[a];
vp[x]=c[a];
vd[x]=d[a];
return;
}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b);
vmi[x]=min(vmi[x<<1],vmi[x<<1|1]);
vma[x]=max(vma[x<<1],vma[x<<1|1]);
vp[x]=max(vp[x<<1],vp[x<<1|1]);
vd[x]=gcd(vd[x<<1],vd[x<<1|1]);
}
void changep(int x,int a,int b,int c,int p){
if(a==b){
vp[x]=p;
return;
}
int mid=(a+b)>>1;
if(c<=mid)changep(x<<1,a,mid,c,p);else changep(x<<1|1,mid+1,b,c,p);
vp[x]=max(vp[x<<1],vp[x<<1|1]);
}
void change(int x,int a,int b,int c,int v,int p){
if(a==b){
vmi[x]=vma[x]=v;
vp[x]=p;
return;
}
int mid=(a+b)>>1;
if(c<=mid)change(x<<1,a,mid,c,v,p);else change(x<<1|1,mid+1,b,c,v,p);
vmi[x]=min(vmi[x<<1],vmi[x<<1|1]);
vma[x]=max(vma[x<<1],vma[x<<1|1]);
vp[x]=max(vp[x<<1],vp[x<<1|1]);
}
void changed(int x,int a,int b,int c,int p){
if(a==b){
vd[x]=p;
return;
}
int mid=(a+b)>>1;
if(c<=mid)changed(x<<1,a,mid,c,p);else changed(x<<1|1,mid+1,b,c,p);
vd[x]=gcd(vd[x<<1],vd[x<<1|1]);
}
void ask(int x,int a,int b,int c,int d){
if(c<=a&&b<=d){
mi=min(mi,vmi[x]);
ma=max(ma,vma[x]);
if(vp[x]>=c)flag=1;
return;
}
int mid=(a+b)>>1;
if(c<=mid)ask(x<<1,a,mid,c,d);
if(d>mid)ask(x<<1|1,mid+1,b,c,d);
}
void askd(int x,int a,int b,int c,int d){
if(c<=a&&b<=d){
g=gcd(g,vd[x]);
return;
}
int mid=(a+b)>>1;
if(c<=mid)askd(x<<1,a,mid,c,d);
if(d>mid)askd(x<<1|1,mid+1,b,c,d);
}
inline bool query(int x,int y,int z){
if(x==y)return 1;
mi=1000000000,ma=flag=g=0;
ask(1,1,n,x,y);
if(!z)return mi==ma;
if(flag)return 0;
if(1LL*(y-x)*z+mi!=ma)return 0;
askd(1,1,n,x,y-1);
return g%z==0;
}
int main(){
read(n),read(m);
for(i=1;i<=n;i++){
read(a[i]);
T[b[i]=getid(a[i])].insert(i);
pre=T[b[i]].find(i);
c[i]=*(--pre);
}
for(i=1;i<n;i++)d[i]=abs(a[i]-a[i+1]);
build(1,1,n);
while(m--){
read(op),read(x),read(y);x^=K,y^=K;
if(op==1){
pre=nxt=T[b[x]].find(x);
pre--,nxt++;
if(*nxt<n)changep(1,1,n,*nxt,*pre);
T[b[x]].erase(x);
b[x]=getid(y);
T[b[x]].insert(x);
pre=nxt=T[b[x]].find(x);
pre--,nxt++;
if(*nxt<n)changep(1,1,n,*nxt,x);
change(1,1,n,x,a[x]=y,*pre);
if(x>1)changed(1,1,n,x-1,abs(a[x-1]-y));
if(x<n)changed(1,1,n,x,abs(y-a[x+1]));
}else{
read(z);
if(query(x,y,z^K))K++,puts("Yes");else puts("No");
}
}
return 0;
}

  

BZOJ4373 : 算术天才⑨与等差数列的更多相关文章

  1. BZOJ4373 算术天才⑨与等差数列 【线段树】*

    BZOJ4373 算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍. 有一天,他给了你一个长度为n的序列,其中第i个数为a[i]. 他想考考你,每次他会给出询问l,r,k ...

  2. 【线段树 集合hash】bzoj4373: 算术天才⑨与等差数列

    hash大法好(@ARZhu):大数相乘及时取模真的是件麻烦事情 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次 ...

  3. [BZOJ4373]算术天才⑨与等差数列(线段树)

    [l,r]中所有数排序后能构成公差为k的等差数列,当且仅当: 1.区间中最大数-最小数=k*(r-l) 2.k能整除区间中任意两个相邻数之差,即k | gcd(a[l+1]-a[l],a[l+2]-a ...

  4. BZOJ4373 算术天才⑨与等差数列(线段树)

    看上去很难维护,考虑找一些必要条件.首先显然最大值-最小值=k*(r-l).然后区间内的数需要模k同余.最后区间内的数两两不同(k=0除外).冷静一下可以发现这些条件组合起来就是充分的了. 考虑怎么维 ...

  5. BZOJ4373 算术天才与等差数列 题解

    题目大意: 一个长度为n的序列,其中第i个数为a[i].修改一个点的值询问区间[l,r]内的数从小到大排序后能否形成公差为k的等差数列. 思路: 1.一段区间符合要求满足:(1)区间中的max-min ...

  6. BZOJ4373: 算术天才⑨与等差数列(线段树 hash?)

    题意 题目链接 Sol 正经做法不会,听lxl讲了一种很神奇的方法 我们考虑如果满足条件,那么需要具备什么条件 设mx为询问区间最大值,mn为询问区间最小值 mx - mn = (r - l) * k ...

  7. bzoj4373 算术天才⑨与等差数列——线段树+set

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4373 一个区间有以 k 为公差的数列,有3个条件: 1.区间 mx - mn = (r-l) ...

  8. 【BZOJ4373】算术天才⑨与等差数列 线段树+set

    [BZOJ4373]算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次他会给出询问l,r,k, ...

  9. 【BZOJ4373】算术天才⑨与等差数列 [线段树]

    算术天才⑨与等差数列 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 算术天才⑨非常喜欢和等 ...

随机推荐

  1. Ubuntu 16.04 下安装Firefox的Flash插件

    在ubuntu系统环境下面打开优酷视频,发现无法播放视频.Adobe Flash Player 是一款轻量级浏览器插件,具有丰富的 Internet 应用运行时间,提供持续的迷人用户体验.绝妙的音频/ ...

  2. [BZOJ2683][BZOJ4066]简单题

    [BZOJ2683][BZOJ4066]简单题 试题描述 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x ...

  3. sed替换字符串时,使用正则表达式的注意事项

    sed的使用方法为: 使用单个模式替换:sed 's/pattern/replacement/flags' filename,例如echo 'abc' | sed 's/a/A/'-->Abc ...

  4. (转)Sublime Text 2 2.0.2 序列号

    ----- BEGIN LICENSE -----Andrew WeberSingle User LicenseEA7E-855605813A03DD 5E4AD9E6 6C0EEB94 BC9979 ...

  5. maven No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?

    maven install项目时出错,提示信息如下: [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-pl ...

  6. Python yield 使用浅析(转)

    Python yield 使用浅析 初学 Python 的开发者经常会发现很多 Python 函数中用到了 yield 关键字,然而,带有 yield 的函数执行流程却和普通函数不一样,yield 到 ...

  7. (转)Sql Server 对锁的初步认识

    一:到底都有哪些锁 学习锁之前,必须要知道锁大概有几种???通常情况下作为码农我们只需知道如下几个锁即可... 1.S(Share)锁 为了方便理解,我们可以直接这么认为,当在select的时候在表, ...

  8. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  9. codeforces A. IQ Test 解题报告

    题目链接:http://codeforces.com/problemset/problem/328/A 一开始单纯地直接判断给出的序列是等差还是等比,连这一句“You should also prin ...

  10. dbVisualizer破解

    下载dbvis.puk,替换C:\Program Files\DbVisualizer\lib\dbvis.jar中的文件. 替换后打开选手动的key:下载地址dbvis.license