设$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. 裸设备和Oracle问答20例

    导读裸设备,也叫裸分区(原始分区),是一种没有经过格式化,不被Unix通过文件系统来读取的特殊字符设备.裸设备可以绑定一个分区,也可以绑定一个磁盘.本文收集裸设备和Oracle问答20例. 1.什么叫 ...

  2. DNS原理及其解析过程【精彩剖析】(转)

      2012-03-21 17:23:10 标签:dig wireshark bind nslookup dns 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否 ...

  3. opencv中,c和c++版本区别体验

    参考:http://www.cnblogs.com/tornadomeet/archive/2012/04/29/2476277.html

  4. HTML 笔记,持续更新

    一.文本格式化标签 <b> 定义粗体文本. <big> 定义大号字. <em> 定义着重文字. <i> 定义斜体字. <small> 定义小 ...

  5. poj1094 拓扑 Sorting It All Out

    Sorting It All Out Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 29744   Accepted: 10 ...

  6. tar: Removing leading `/’ from member names

    tar: Removing leading `/’ from member names+2 分类:Web服务器 标签:tar 3,910人浏览   这并不是一个错误,而是一个警告,原因很简单,就是你在 ...

  7. 【VirtualBox】VirtualBox的桥接网络模式,为啥网络不稳定?

    网桥模式访问外网非常慢,经常卡死,ping时断时续 七搞八搞,反复重启了几次 TMD  就好了,也不知道什么情况,VirtualBox还是不太好使啊..... 网桥模式 设置 如下: 参考资料: ht ...

  8. intellij idea 如何更改编辑器文本字体和大小

    换上了intellij idea之后,第一件事就是想要改变下文字字体,因为在我这个27寸的2k分辨率的屏幕上,文字显然太小了. intellij idea字体设值分成两部分,一部分是UI部分字体字号设 ...

  9. Lowest Common Ancestor

    Given the root and two nodes in a Binary Tree. Find the lowest common ancestor(LCA) of the two nodes ...

  10. css调用外部样式和css样式说明剧中显示

    <title>边走边乔</title><link href="css/style.css" rel="stylesheet" ty ...