BZOJ4373 算术天才⑨与等差数列(线段树)
看上去很难维护,考虑找一些必要条件。首先显然最大值-最小值=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 算术天才⑨与等差数列(线段树)的更多相关文章
- [BZOJ4373]算术天才⑨与等差数列(线段树)
[l,r]中所有数排序后能构成公差为k的等差数列,当且仅当: 1.区间中最大数-最小数=k*(r-l) 2.k能整除区间中任意两个相邻数之差,即k | gcd(a[l+1]-a[l],a[l+2]-a ...
- 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 ...
随机推荐
- 汇编:将指定的内存中连续N个字节填写成指定的内容
1.loop指令实现 ;=============================== ;循环程序设计 ;将制定内存中连续count个字节填写成指定内容(te) ;loop指令实现 DATAS SEG ...
- php接口编程
1:自定义接口编程 对于自定义接口最关键就是写接口文档,在接口文档中规定具体的请求地址以及方式,还有具体的参数信息 2:接口文档编写 请求地址 http://jxshop.com/Api/login ...
- Chrome浏览器调试移动端网页 chrome://inspect/#devices
我使用的是魅族(魅蓝NOTE6 ),电脑是win 7系统,以下几步就可以轻松使用浏览器内置的功能调试移动端网页了: 注意:谷歌浏览器需要先FQ,不然调试页面会空白或者报404错误,(不会FQ的可以联系 ...
- nodeJs 对 Mysql 数据库的 curd
var mysql = require('mysql'); var connection = mysql.createConnection({ host : 'localhost', user : ' ...
- CSS 转载
CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). CSS语法 CSS实例 ...
- redhat6.5安装oracle 11g
1.修改操作系统核心参数 在Root用户下执行以下步骤: 1)修改用户的SHELL的限制,修改/etc/security/limits.conf文件 输入命令:vi /etc/security/lim ...
- Unicode控制字符
Unicode控制字符就是特殊的Unicode字符 控制字符转义代码对照表 Unicode-控制字符 LRM RLM ZWJ ZWNJ LRE LRO RLO PDF NADS ...
- ubuntu下安装LAMP环境遇到的一些小问题
0x00 今天在服务器上重新弄了一下lamp环境 安装的过程中遇到了不少小问题 记录一下解决的方案吧 服务器安装的是ubuntu 16.04.1 0x01 首先在用 apt-get install 安 ...
- 揭秘css
这是我看到非常好的一本电子教程,可以当参考手册使用,链接
- 在PXC中重新添加掉线节点
Preface When we add a new node into PXC structure,it will estimate the mothed(IST/SST) to tr ...