[BZOJ4373]算术天才⑨与等差数列(线段树)
[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]算术天才⑨与等差数列(线段树)的更多相关文章
- bzoj4373 算术天才⑨与等差数列——线段树+set
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4373 一个区间有以 k 为公差的数列,有3个条件: 1.区间 mx - mn = (r-l) ...
- BZOJ4373: 算术天才⑨与等差数列(线段树 hash?)
题意 题目链接 Sol 正经做法不会,听lxl讲了一种很神奇的方法 我们考虑如果满足条件,那么需要具备什么条件 设mx为询问区间最大值,mn为询问区间最小值 mx - mn = (r - l) * k ...
- 【BZOJ4373】算术天才⑨与等差数列 线段树+set
[BZOJ4373]算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次他会给出询问l,r,k, ...
- 【BZOJ4373】算术天才⑨与等差数列 [线段树]
算术天才⑨与等差数列 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 算术天才⑨非常喜欢和等 ...
- BZOJ 4373 算术天才⑨与等差数列 线段树+set(恶心死我了)
mdzz,这道题重构了4遍,花了一个晚上... 满足等差数列的条件: 1. 假设min是区间最小值,max是区间最大值,那么 max-min+k(r−l) 2. 区间相邻两个数之差的绝对值的gcd=k ...
- BZOJ 4373算术天才⑨与等差数列(线段树)
题意:给你一个长度为n的序列,有m个操作,写一个程序支持以下两个操作: 1. 修改一个值 2. 给出三个数l,r,k, 询问:如果把区间[l,r]的数从小到大排序,能否形成公差为k的等差数列. n,m ...
- BZOJ 4373: 算术天才⑨与等差数列 线段树
Description 算术天才⑨非常喜欢和等差数列玩耍. 有一天,他给了你一个长度为n的序列,其中第i个数为a[i]. 他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序后能 ...
- bzoj 4373 算术天才⑨与等差数列——线段树+set
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4373 能形成公差为k的等差数列的条件:mx-mn=k*(r-l) && 差分 ...
- BZOJ4373 算术天才⑨与等差数列 【线段树】*
BZOJ4373 算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍. 有一天,他给了你一个长度为n的序列,其中第i个数为a[i]. 他想考考你,每次他会给出询问l,r,k ...
随机推荐
- LintCode 402: Continuous Subarray Sum
LintCode 402: Continuous Subarray Sum 题目描述 给定一个整数数组,请找出一个连续子数组,使得该子数组的和最大.输出答案时,请分别返回第一个数字和最后一个数字的下标 ...
- 洛谷 Sorting a Three-Valued Sequence 三值的排序
Description 排序是一种很频繁的计算任务.现在考虑最多只有三值的排序问题.一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌序的时候. 在这个任务中可能的值只有三种1,2和3.我们用交换的 ...
- 设置display:inline-block产生间隙
display:inline-block产生间隙,是由于换行在内的空白符 display:inline-block在IE下仅仅是触发了layout,而它本是行布局,触发后,块元素依然还是行布局.所以需 ...
- 技巧之如何快速使用websocket来监控标准输出
为啥是Websocket 服务端可以主动推送消息到浏览器端.比如服务端实时在打印日志,这是一个标准输出,可以实时将日志推送到浏览器. 为啥用websocketd (https://github.com ...
- PHP对象3: public / private / protected
<?php /* public 可继承, 内外可访问 private 不可, 只内部访问 protected 可继承, 只内部 */ class A{ protected $name; priv ...
- C++ 模板特化以及Typelist的相关理解
近日,在学习的过程中第一次接触到了Typelist的相关内容,比如Loki库有一本Modern C++ design的一本书,大概JD搜了一波没有译本,英文版600多R,瞬间从价值上看到了这本书的价值 ...
- React 16 源码瞎几把解读 【三 点 二】 react中的fiberRoot
〇.先来看看常用的常量 NoWork = 0 noTimeout = undefined HostRoot = 3 NoContext = 0b000; AsyncMode = 0b001; Stri ...
- 很多人都没用过的轻量级Oracle数据库数据导出工具SQLLDR2——性能超赞
SQLLDR2 介绍 每周发表一篇数据库或大数据相关的帖子,敬请关注 1. 工具介绍 Sqluldr2(SQL * UnLoader 第二版)是灵活与强大的 Oracle 文本导出程序,已被大众使 用 ...
- vuex实例详解
vuex是一个专门为vue.js设计的集中式状态管理架构.状态?把它理解为在data中的属性需要共享给其他vue组件使用的部分. 简单的说就是data需要共用的属性 一.小demo 已经用Vue脚手架 ...
- centos7下vi的用法
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...