设$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 安装 VMware-Workstation-12

    以前一直使用 Ubuntu + Virtaulbox ,最近测试了 VMware-Workstation-9,性能超过 Virtaulbox-4.2.x,下面是详细步骤: 1 首先准备一个Ubuntu ...

  2. 【Other】千字文 硬笔 楷书 字帖

    <千字文>是我国最优秀的一篇训蒙教材,用一千个汉字勾划出一部完整的中国文化史的基本轮廓,代表了中国传统教育启蒙阶段的最高水平.<千字文>通篇首尾连贯,音韵谐美,读起来朗朗上口, ...

  3. 基础知识《六》---Java集合类: Set、List、Map、Queue使用场景梳理

    本文转载自LittleHann 相关学习资料 http://files.cnblogs.com/LittleHann/java%E9%9B%86%E5%90%88%E6%8E%92%E5%BA%8F% ...

  4. 《ASP.NET MVC4 WEB编程》学习笔记------Entity Framework的Database First、Model First和Code Only三种开发模式

    作者:张博出处:http://yilin.cnblogs.com Entity Framework支持Database First.Model First和Code Only三种开发模式,各模式的开发 ...

  5. CSS本页写样式

    <style type="text/css">p{ color:#ff0000; font-size:24px; font-family:"隶书"; ...

  6. 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 ...

  7. 【转】SQL删除重复记录,只保留其中一条

    SQL:删除重复数据,只保留一条用SQL语句,删除掉重复项只保留一条在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢 1.查找表中多余的重复记录,重复记录是根据单个字段(peop ...

  8. Android runProguard配置 导致module lib 中的包编译时无法识别

    今天写代码时用到了另一个lib型的工程,把它添加到dependencies后,在原工程中可以引用lib中的文件了,但是编译时就会报错,提示包不存在,后来在build.gradle中设置runProgu ...

  9. Objective-C 和 C++中指针的格式和.方法 和内存分配

    最近在看cocos2d-x,于是打算复习一下C++,在这里简单对比下,留个念想. 先看看oc中指针的用法 @interface ViewController : UIViewController { ...

  10. 在Xcode5和Android Studio添加工程间的依赖

    正在编辑中,尚未完成 先看看ios的target是什么,请先参看http://www.cocoachina.com/bbs/read.php?tid-10884.html做个大概了解 这里有一篇文章, ...