[l,r]中所有数排序后能构成公差为k的等差数列,当且仅当

1.区间中最大数-最小数=k*(r-l)

2.k能整除区间中任意两个相邻数之差,即k | gcd(a[l+1]-a[l],a[l+2]-a[l+1],...,a[r]-a[r-1])

3.区间中任意两个数不相同,即设pre[i]为序列中i之前第一个与a[i]相等的数的位置,则max(pre[l],...,pre[r])<l

于是线段树分别维护:区间最大值,区间最小值,区间相邻差的gcd,区间pre的最大值即可。

注意特判下l=r和k=0的情况。

 #include<set>
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls (x<<1)
#define rs (ls|1)
#define lson ls,L,mid
#define rson rs,mid+1,R
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
using namespace std; const int N=;
int n,m,tot,op,x,y,l,r,k,w,a[N],d[N],pre[N],Gcd[N<<],mn[N<<],mx[N<<],mxp[N<<];
set<int>S[N<<];
map<int,int>mp; int gcd(int a,int b){ return b ? gcd(b,a%b) : a; } void upd(int x){
mn[x]=min(mn[ls],mn[rs]); mx[x]=max(mx[ls],mx[rs]);
Gcd[x]=gcd(Gcd[ls],Gcd[rs]); mxp[x]=max(mxp[ls],mxp[rs]);
} void build(int x,int L,int R){
if (L==R){ Gcd[x]=d[L]; mn[x]=mx[x]=a[L]; mxp[x]=pre[L]; return; }
int mid=(L+R)>>;
build(lson); build(rson); upd(x);
} void mdf(int x,int L,int R,int pos,int k,int op){
if (L==R){
if (op==) Gcd[x]=k;
if (op==) mn[x]=mx[x]=k;
if (op==) mxp[x]=k;
return;
}
int mid=(L+R)>>;
if (pos<=mid) mdf(lson,pos,k,op); else mdf(rson,pos,k,op);
upd(x);
} int que(int x,int L,int R,int l,int r,int op){
if (L==l && r==R){
if (op==) return Gcd[x];
if (op==) return mn[x];
if (op==) return mx[x];
if (op==) return mxp[x];
}
int mid=(L+R)>>;
if (r<=mid) return que(lson,l,r,op);
else if (l>mid) return que(rson,l,r,op);
else{
if (op==) return gcd(que(lson,l,mid,op),que(rson,mid+,r,op));
if (op==) return min(que(lson,l,mid,op),que(rson,mid+,r,op));
if (op==) return max(que(lson,l,mid,op),que(rson,mid+,r,op));
if (op==) return max(que(lson,l,mid,op),que(rson,mid+,r,op));
}
return ;
} int main(){
freopen("bzoj4373.in","r",stdin);
freopen("bzoj4373.out","w",stdout);
scanf("%d%d",&n,&m);
rep(i,,n){
scanf("%d",&a[i]),d[i]=abs(a[i]-a[i-]);
if (!mp.count(a[i])){
mp[a[i]]=++tot; pre[i]=; S[tot].insert(i);
}else{
int t=mp[a[i]]; pre[i]=*(--S[t].end()); S[t].insert(i);
}
}
build(,,n);
rep(i,,m){
scanf("%d",&op);
if (op==){
scanf("%d%d",&x,&y); x^=w; y^=w;
if (y==a[x]) continue;
d[x]=abs(y-a[x-]); mdf(,,n,x,d[x],);
if (x<n) d[x+]=abs(a[x+]-y),mdf(,,n,x+,d[x+],);
int t=mp[a[x]]; set<int>::iterator it=S[t].upper_bound(x);
if (it!=S[t].end()) pre[*it]=pre[x],mdf(,,n,*it,pre[*it],); S[t].erase(x);
a[x]=y; mdf(,,n,x,a[x],);
if (!mp.count(a[x])){
mp[a[x]]=++tot; pre[x]=; S[tot].insert(x); mdf(,,n,x,pre[x],);
}else{
int t=mp[a[x]];
set<int>::iterator it=S[t].insert(x).first;
if (it==S[t].begin()) pre[x]=; else pre[x]=*(--it);
mdf(,,n,x,pre[x],);
it=S[t].upper_bound(x);
if (it!=S[t].end()) pre[*it]=x,mdf(,,n,*it,pre[*it],);
}
}else{
scanf("%d%d%d",&l,&r,&k); l^=w; r^=w; k^=w;
if (l==r){ w++; puts("Yes"); continue; }
if (!k){
if (que(,,n,l,r,)==que(,,n,l,r,)) w++,puts("Yes"); else puts("No");
continue;
}
if (que(,,n,l,r,)-que(,,n,l,r,)!=1ll*k*(r-l) || que(,,n,l+,r,)%k || que(,,n,l,r,)>=l) puts("No");
else w++,puts("Yes");
}
}
return ;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 【Atcoer】ARC088 E - Papple Sort

    [题目]E - Papple Sort [题意]给定长度为n的小写字母串,只能交换相邻字母,求形成回文串的最小步数.n<=2*10^5. [算法]数学 [题解]官方题解 本题题解中有以下重要的思 ...

  2. python 版本zabbix_sender

    python版本的zabbix_sender: 使用方法:    1.导入 : from zbx_send import info        2.实例化: test=info()     3.支持 ...

  3. 【leetcode 简单】 第七题 合并两个有序链表

    将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1->1->2- ...

  4. 关于linux的一些基础知识

    一.基础 1.linux所有内容以文件形式保存,包括硬件. 2.linux 不区分扩展名,靠权限区分.   #但是,约定 .sh脚本文件  .conf配置文件. 3.-rw-r--r--        ...

  5. three.js为何如此奇妙

    WebGL是在浏览器中实现三维效果的一套规范,而最初使用WebGL原生的API来写3D程序是一件非常痛苦的事情,在辛苦的付出下WebGL开源框架出现了,其中three.js就是非常优秀的一个,它掩盖了 ...

  6. python基础之常用的高阶函数

    前言 高阶函数指的是能接收函数作为参数的函数或类:python中有一些内置的高阶函数,在某些场合使用可以提高代码的效率. map() map函数可以把一个迭代对象转换成另一个可迭代对象,不过在pyth ...

  7. Linux sqlite3基本命令

    简介sqlite3一款主要用于嵌入式的轻量级数据库,本文旨在为熟悉sqlite3基本命令提供技术文档. 备注:本文所有操作均在root用户下进行. 1.安装sqlite3 ubuntu下安装sqlit ...

  8. URAL题解二

    URAL题解二 URAL 1082 题目描述:输出程序的输入数据,使得程序输出"Beutiful Vasilisa" solution 一开始只看程序的核心部分,发现是求快排的比较 ...

  9. 服务号使用微信网页授权(H5应用等)

    获取授权准备 AppId 服务号已经认证且获取到响应接口权限 设置网页授权域名 公众号设置 - 功能设置 - 网页授权域名.注意事项: 回调页面域名或路径需使用字母.数字及"-"的 ...

  10. 计算 Python (list or array) 相同索引元素相等的个数

    上代码: a = [2, 3, 3, 1, 1, 3, 3, 3, 2, 1, 3, 1, 3, 2, 2, 2, 3, 1, 2, 3, 2, 3, 1, 1, 2, 1, 1, 1, 2, 2, ...