BZOJ4373 : 算术天才⑨与等差数列
设$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 : 算术天才⑨与等差数列的更多相关文章
- BZOJ4373 算术天才⑨与等差数列 【线段树】*
BZOJ4373 算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍. 有一天,他给了你一个长度为n的序列,其中第i个数为a[i]. 他想考考你,每次他会给出询问l,r,k ...
- 【线段树 集合hash】bzoj4373: 算术天才⑨与等差数列
hash大法好(@ARZhu):大数相乘及时取模真的是件麻烦事情 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次 ...
- [BZOJ4373]算术天才⑨与等差数列(线段树)
[l,r]中所有数排序后能构成公差为k的等差数列,当且仅当: 1.区间中最大数-最小数=k*(r-l) 2.k能整除区间中任意两个相邻数之差,即k | gcd(a[l+1]-a[l],a[l+2]-a ...
- BZOJ4373 算术天才⑨与等差数列(线段树)
看上去很难维护,考虑找一些必要条件.首先显然最大值-最小值=k*(r-l).然后区间内的数需要模k同余.最后区间内的数两两不同(k=0除外).冷静一下可以发现这些条件组合起来就是充分的了. 考虑怎么维 ...
- BZOJ4373 算术天才与等差数列 题解
题目大意: 一个长度为n的序列,其中第i个数为a[i].修改一个点的值询问区间[l,r]内的数从小到大排序后能否形成公差为k的等差数列. 思路: 1.一段区间符合要求满足:(1)区间中的max-min ...
- BZOJ4373: 算术天才⑨与等差数列(线段树 hash?)
题意 题目链接 Sol 正经做法不会,听lxl讲了一种很神奇的方法 我们考虑如果满足条件,那么需要具备什么条件 设mx为询问区间最大值,mn为询问区间最小值 mx - mn = (r - l) * k ...
- bzoj4373 算术天才⑨与等差数列——线段树+set
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4373 一个区间有以 k 为公差的数列,有3个条件: 1.区间 mx - mn = (r-l) ...
- 【BZOJ4373】算术天才⑨与等差数列 线段树+set
[BZOJ4373]算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次他会给出询问l,r,k, ...
- 【BZOJ4373】算术天才⑨与等差数列 [线段树]
算术天才⑨与等差数列 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 算术天才⑨非常喜欢和等 ...
随机推荐
- [Effective JavaScript 笔记]第55条:接收关键字参数的选项对象
53节建议保持参数顺序的一致约定对于帮助程序员记住每个参数在函数调用中的意义很重要.参数较少这个主意不错,但如果参数过多后,就出现麻烦了,记忆和理解起来都不太容易. 参数蔓延 如下面这些代码: var ...
- Unix如何轻松快速复制
笔者在实践中总结了一套Unix操作系统硬盘的快速复制方法,成功地运用于建行几大Unix操作系统网络的建设中,收到了良好的效果.现将该方法介绍如下,供读者参考. 系统要求,两台主机软尽量相同.要求被复制 ...
- 在mac上安装nodejs
文章转载自我的个人博客 www.iwangzheng.com node.js最初是2009年发布的,目标是为聊实现事件驱动和非阻塞I/O的web服务器,应用的场景非常的广泛,有web服务器.实时应用 ...
- Coursera台大机器学习课程笔记8 -- Linear Regression
之前一直在讲机器为什么能够学习,从这节课开始讲一些基本的机器学习算法,也就是机器如何学习. 这节课讲的是线性回归,从使Ein最小化出发来,介绍了 Hat Matrix,要理解其中的几何意义.最后对比了 ...
- 配置caffe的python环境时make pycaffe提示fatal error: numpy/arrayobject.h No such file or directory解决方法
重装numpy: sudo pip uninstall numpy sudo pip install numpy 是没有用的... 解决的办法就是: sudo apt-get install pyth ...
- Linux Apache 怎么修改工作模式
Apache默认为prefork模式,主要是考虑到稳定性的原因. 要切换到worker模式,则需要登录到linux上,进行如下操作: 进入/usr/sbin目录 cd /usr/sbin 将当前的pr ...
- 【云计算】Docker Nginx示例
使用数据卷容器,配置Nginx Docker作为静态文件服务器 . 该方法是直接使用命令行,当然也可使用Dockerfile文件进行创建. 其实,使用docker创建nginx容器是很简单的,但要和数 ...
- 如何手动修改XP系统属性中的技术支持信息
\windows\system32目录下有个oeminof.ini,里面是OEM显示的文字信息,把相应项目修改即可,OEM图片使用的是本目录下的OEMlogo.bmp(图片:创建一个图形文件,像素尺寸 ...
- Android之ViewDragHelper
在自定义ViewGroup中,很多效果都包含用户手指去拖动其内部的某个View(eg:侧滑菜单等),针对具体的需要去写好onInterceptTouchEvent和onTouchEvent这两个方法是 ...
- OOP 7大原则
1. 开闭原则(Open-Closed Principle,OCP) 1)定义:一个软件实体应当对扩展开放,对修改关闭( Software entities should be open for e ...