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 ...
随机推荐
- Ajax知识总结
一 AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 不是新的编程语言,而是一种使用现有标准的新方法.AJAX 最大 ...
- 搭建ssm框架经验
要想搭建好ssm框架的开发环境.首先我们需要知道ssm是什么?ssm就是spring,springmvc,mybatis. 然后我们要知道,他们分别都是怎样实现的和做什么用的,充当什么角色?这样我们就 ...
- JS如何给ul下的所有li绑定点击事件,点击使其弹出下标和内容
这是一个非常常见的面试题,出题方式多样,但考察点相同,下面我们来看看这几种方法:方法一: var itemli = document.getElementsByTagName("li&quo ...
- js中面向对象(创建对象的几种方式)
1.面向对象编程(OOP)的特点: 抽象:抓住核心问题 封装:只能通过对象来访问方法 继承:从已有的对象下继承出新的对象 多态:多对象的不同形态 一.创建对象的几种方式 javascript 创建对象 ...
- ThinkPHP框架介绍
什么是框架 php框架是许多代码的集合,这些代码的程序结构的代码(并不是业务代码)代码中有许多的函数,类,功能类包 不使用框架开发的缺陷 代码编写不规范 牵一发而动全身 不能很好满足客户各方面的需求 ...
- django的模型和基本的脚本命令
python manage.py startproject project_name 创建一个django项目 python manage.py startapp app_name 创建一个app ...
- 【struts2】struts2的使用
1.使用步骤 1) 导入struts2的支持jar包 名称 说明 struts2-core-2.3.4.1.jar Structs2的核心类库 xwork-core-2.3.4.1.jar xwork ...
- Failed to read candidate component class错误分析
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component c ...
- C++11中std::forward的使用
std::forward argument: Returns an rvalue reference to arg if arg is not an lvalue reference; If arg ...
- 11 TCP实现QQ聊天
1.客户端参考代码 #coding=utf-8 from socket import * # 创建socket tcpClientSocket = socket(AF_INET, SOCK_STREA ...