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

  考虑怎么维护。最大值最小值非常简单。模k同余相当于区间内相邻两数的差都是k的倍数,可以维护差分数组的gcd。两两不同相当于区间内没有出现次数>1的数,对每个数用set维护上一个和他相同的数的位置,线段树维护,区间查询max,如果<l则说明不存在。

  开始判断是否不同的写出锅了,结果删掉竟然过了23333

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<cassert>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 300010
#define ll long long
int n,m,a[N],b[N],lst,cnt;
map<int,int> f;
set<int> pre[N<<];
int L[N<<],R[N<<],mn[N<<],mx[N<<],GCD[N<<],last[N<<];
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
void up(int k)
{
mn[k]=min(mn[k<<],mn[k<<|]);
mx[k]=max(mx[k<<],mx[k<<|]);
last[k]=max(last[k<<],last[k<<|]);
GCD[k]=gcd(GCD[k<<],GCD[k<<|]);
}
void build(int k,int l,int r)
{
L[k]=l,R[k]=r;
if (l==r)
{
mn[k]=mx[k]=a[l];GCD[k]=b[l];
last[k]=*(--pre[f[a[l]]].find(l));
return;
}
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
up(k);
}
void modify(int k,int p,int x,int op)
{
if (L[k]==R[k])
{
if (op==) mn[k]=mx[k]=x;
else if (op==) GCD[k]=x;
else last[k]=x;
return;
}
int mid=L[k]+R[k]>>;
if (p<=mid) modify(k<<,p,x,op);
else modify(k<<|,p,x,op);
up(k);
}
int qmax(int k,int l,int r)
{
if (L[k]==l&&R[k]==r) return mx[k];
int mid=L[k]+R[k]>>;
if (r<=mid) return qmax(k<<,l,r);
else if (l>mid) return qmax(k<<|,l,r);
else return max(qmax(k<<,l,mid),qmax(k<<|,mid+,r));
}
int qmin(int k,int l,int r)
{
if (L[k]==l&&R[k]==r) return mn[k];
int mid=L[k]+R[k]>>;
if (r<=mid) return qmin(k<<,l,r);
else if (l>mid) return qmin(k<<|,l,r);
else return min(qmin(k<<,l,mid),qmin(k<<|,mid+,r));
}
int qgcd(int k,int l,int r)
{
if (L[k]==l&&R[k]==r) return GCD[k];
int mid=L[k]+R[k]>>;
if (r<=mid) return qgcd(k<<,l,r);
else if (l>mid) return qgcd(k<<|,l,r);
else return gcd(qgcd(k<<,l,mid),qgcd(k<<|,mid+,r));
}
int qlast(int k,int l,int r)
{
if (L[k]==l&&R[k]==r) return last[k];
int mid=L[k]+R[k]>>;
if (r<=mid) return qlast(k<<,l,r);
else if (l>mid) return qlast(k<<|,l,r);
else return max(qlast(k<<,l,mid),qlast(k<<|,mid+,r));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("bzoj4373.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
for (int i=;i<=n;i++)
{
a[i]=read(),b[i]=abs(a[i]-a[i-]);
if (f.find(a[i])==f.end()) f[a[i]]=++cnt,pre[cnt].insert();
pre[f[a[i]]].insert(i);
}
build(,,n);
while (m--)
{
int op=read();
if (op==)
{
int p=read()^lst,x=read()^lst;
int t=f[a[p]];set<int>::iterator it=++pre[t].find(p);
if (it!=pre[t].end()) modify(,*it,*(--pre[t].find(p)),);
pre[t].erase(p);
a[p]=x;modify(,p,x,);
modify(,p,abs(a[p]-a[p-]),);
if (p<=n) modify(,p+,abs(a[p+]-a[p]),);
if (f.find(a[p])==f.end()) f[a[p]]=++cnt,pre[cnt].insert();
t=f[a[p]];it=pre[t].lower_bound(p);
if (it!=pre[t].end()) modify(,*it,p,);
it--;modify(,p,*it,);pre[t].insert(p);
}
else
{
int l=read()^lst,r=read()^lst,d=read()^lst;
if (qmax(,l,r)-qmin(,l,r)==1ll*d*(r-l)&&(d==||l==r||((qgcd(,l+,r)%d==)&&qlast(,l,r)<l))) lst++,printf("Yes\n");
else printf("No\n");
}
}
return ;
}

BZOJ4373 算术天才⑨与等差数列(线段树)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. BZOJ 4373 算术天才⑨与等差数列 线段树+set(恶心死我了)

    mdzz,这道题重构了4遍,花了一个晚上... 满足等差数列的条件: 1. 假设min是区间最小值,max是区间最大值,那么 max-min+k(r−l) 2. 区间相邻两个数之差的绝对值的gcd=k ...

  7. BZOJ 4373算术天才⑨与等差数列(线段树)

    题意:给你一个长度为n的序列,有m个操作,写一个程序支持以下两个操作: 1. 修改一个值 2. 给出三个数l,r,k, 询问:如果把区间[l,r]的数从小到大排序,能否形成公差为k的等差数列. n,m ...

  8. BZOJ 4373: 算术天才⑨与等差数列 线段树

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

  9. bzoj 4373 算术天才⑨与等差数列——线段树+set

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4373 能形成公差为k的等差数列的条件:mx-mn=k*(r-l) && 差分 ...

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

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

随机推荐

  1. JavaScript实现图片切换

    页面内容:一个按钮标签  一个Img标签 实现原理:通过修改Img标签的src属性,实现图片的切换 备注:代码中flag变量仅仅用作标记,也可以直接用Img标签的src属性进行判断,不过在判断时候不能 ...

  2. MAthJax入门教程(五分钟上手)

    最近在研究,在页面中显示一些数学公式.搞得我很头疼. 据说MathJax会统一这已领域.所以去学了学.网上教程特别多.繁杂. 说的清楚的特别少. 我是这么跑通的,: 1.在官网下载代码地址为:http ...

  3. Vue项目中使用vw实现移动端适配

    我们在vue移动端项目中的适配一般都采用rem,但是rem也不是能兼容所有的终端. 随着viewport单位越来越受到众多浏览器的支持,下面将简单介绍怎么实现vw的兼容问题,用vw代替rem 当我们采 ...

  4. PHP中文乱码分类及解决办法大全

    PHP+MYSQL做网站开发通常都会碰到浏览器输出中文字符时乱码,这个问题的原因主要是因为HTML内容编码,PHP文件编码和MySQL数据库编码这三者不一致造成的.下面我们以UTF-8为例简述一下如何 ...

  5. 分享一个工作中遇得到的sql(按每天每人统计拖车次数与小修次数)

    查询每人每天的数据 首先先建表 CREATE TABLE `user` ( `name` ) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CR ...

  6. 如何在Moodle中显示PPT课件

    Moodle中目前是不直接支持PPT的,所以需要曲线救国: 1.安装 iSpring Free 8版本,免费版,其实是一个PPT的插件,在PPT的工具栏中有显示. 2.打开PPT后,直接在该工具中进行 ...

  7. 【转】mui 通过JSON动态的生成列表

    <script type="text/template" id="radio-tigan"> <%for(var i=0;i<recor ...

  8. 当应用出现 access violation at address in module时

    Delphi2010和XE10,midas是不同的版本,之前开发的两个系统,基于不同的Delphi版本,经常出现access violation at address in module错误.特别是当 ...

  9. 一步一步学Linq to sql(六):探究特性

    延迟执行 IQueryable query = from c in ctx.Customers select c; 这样的查询句法不会导致语句立即执行,它仅仅是一个描述,对应一个SQL.仅仅在需要使用 ...

  10. Android——搜索传统蓝牙设备

    一,主布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro ...