[线段树]洛谷P5278 算术天才⑨与等差数列
题目描述
算术天才⑨非常喜欢和等差数列玩耍。 有一天,他给了你一个长度为n的序列,其中第i个数为a[i]。 他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序后能否形成公差为k的等差数列。 当然,他还会不断修改其中的某一项。 为了不被他鄙视,你必须要快速并正确地回答完所有问题。 注意:只有一个数的数列也是等差数列。
输入输出格式
输入格式:
第一行包含两个正整数n,m(1<=n,m<=300000),分别表示序列的长度和操作的次数。 第二行包含n个整数,依次表示序列中的每个数ai。 接下来m行,每行一开始为一个数op, 若op=1,则接下来两个整数x,y(1<=x<=n,0<=y<=10^9),表示把a[x]修改为y。 若op=2,则接下来三个整数l,r,k(1<=l<=r<=n,0<=k<=10^9),表示一个询问。 在本题中,x,y,l,r,k都是经过加密的,都需要异或你之前输出的Yes的个数来进行解密。
输出格式:
输出若干行,对于每个询问,如果可以形成等差数列,那么输出Yes,否则输出No。
分析:
题目中要求查询一段区间内的数能否构成公差为K的等差数列。由于等差数列本身不好维护,那么我们就可以去找区间内的数能构成等差数列的等价条件,再维护这些条件即可。
通过看别人的题解,我们可以得到这些条件:
1.这些数不相同。(废话)
2.最大值减去最小值等于(l-r)k。(直接套公式,还是挺显然的)
3.所有相邻两数的差的gcd都为k,即都为k的倍数。(????????)
等差数列肯定满足以上条件,所以我们只需要来伪证一下它的充分性即可。
首先,所有相邻两数的差都是k的倍数,那么我们可以知道任意两数的差都是k的倍数,因为 任意两数的差 都可以用几个 相邻两数的差 通过加减得到。
所以,所有数与最小值的差都是k的倍数。这段区间最大值与最小值的差是(l-r)k,所以每个数与最小值做差得到的值不会超过(l-r)k那么这些差就只有0,k,2k,3k.....(l-r)k这(l-r+1)种情况。又因为这段区间有(l-r+1)个且互不相同的数,所以只有可能是把拿(l-r+1)种情况都占满了的,也就是等差数列。
在伪证完了之后,我们来考虑如何维护这些性质。鉴于是区间查询,所以考虑线段树维护。最大值和最小值不用说,gcd只需要记录一个数和它下一个数的差,再与其它差求gcd,查询只需要查询(l,r-1)即可。至于如何确定这些数不同,我们需要用一个pre数组记录每个位置的 上一个与这个位置有相同值的位置的编号,查询时只需要查询最大的pre,只要它小于l就行。我们可以先将值离散,再把拥有相同值的位置的编号丢将进set里让它自动排序,就可以维护pre数组了。
代码如下(自带常数大性质的我开了o2才水过,还不如去维护区间平方和和立方和碰碰运气)
#include<set>
#include<map>
#include<cstdio>
#include<algorithm>
#define lch (id<<1)
#define rch ((id<<1)+1)
#define mid ((l+r)>>1)
#define maxn 300005
using namespace std;map<int,int >ma;
set<int>s[maxn<<];set<int>::iterator nex,bef;
int n,m,ny,cnt,a[maxn],ori[maxn],pre[maxn];
int mxp[maxn<<],minn[maxn<<],maxx[maxn<<],G[maxn<<];
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int find(int num)
{
int id;if(ma.count(num))return ma[num];
id=ma[num]=++cnt;s[id].insert();s[id].insert(n+);return id;
}
void fix(int l,int r,int id,int i)
{
if(i<l||r<i)return;
if(l==r){minn[id]=maxx[id]=a[i];mxp[id]=pre[i];G[id]=abs(a[i]-a[i+]);return;}
fix(l,mid,lch,i);fix(mid+,r,rch,i);
minn[id]=min(minn[lch],minn[rch]);
maxx[id]=max(maxx[lch],maxx[rch]);
mxp[id]=max(mxp[lch],mxp[rch]);G[id]=gcd(G[rch],G[lch]);
}
int q1(int l,int r,int id,int l1,int r1)
{
if(r1<l||r<l1)return ;
if(l1<=l&&r<=r1)return maxx[id];
return max(q1(l,mid,lch,l1,r1),q1(mid+,r,rch,l1,r1));
}
int q2(int l,int r,int id,int l1,int r1)
{
if(r1<l||r<l1)return ;
if(l1<=l&&r<=r1)return minn[id];
return min(q2(l,mid,lch,l1,r1),q2(mid+,r,rch,l1,r1));
}
int ansgcd;
void q3(int l,int r,int id,int l1,int r1)
{
if(r1<l||r<l1)return;
if(l1<=l&&r<=r1)
{
if(ansgcd==-)ansgcd=G[id];
else ansgcd=gcd(ansgcd,G[id]);return;
}
q3(l,mid,lch,l1,r1);q3(mid+,r,rch,l1,r1);
}
int q4(int l,int r,int id,int l1,int r1)
{
if(r1<l||r<l1)return ;
if(l1<=l&&r<=r1)return mxp[id];
return max(q4(l,mid,lch,l1,r1),q4(mid+,r,rch,l1,r1));
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);s[ori[i]=find(a[i])].insert(i);
bef=s[ori[i]].find(i);bef--;pre[i]=*bef;
fix(,n,,i);if(i>)fix(,n,,i-);
}
for(int t=,ord,x,l,r,k;t<=m;t++)
{
scanf("%d",&ord);
if(ord==)
{
scanf("%d%d",&x,&k);x^=ny;k^=ny;
nex=s[ori[x]].find(x);nex++;
if(*nex!=n+){pre[*nex]=pre[x];fix(,n,,*nex);}
s[ori[x]].erase(x);
s[ori[x]=find(a[x]=k)].insert(x);
nex=s[ori[x]].find(x);nex++;
pre[x]=pre[*nex];
if(*nex!=n+){pre[*nex]=x;fix(,n,,*nex);}
fix(,n,,x);
if(x>)fix(,n,,x-);
}
if(ord==)
{
scanf("%d%d%d",&l,&r,&k);l^=ny;r^=ny;k^=ny;
if(l==r){printf("Yes\n"),ny++;continue;}
int mx=q1(,n,,l,r),mn=q2(,n,,l,r),p=q4(,n,,l,r),g;
ansgcd=-;q3(,n,,l,r-);g=ansgcd;
if(k==&&mx-mn==){printf("Yes\n"),ny++;continue;}
if(k==&&mx-mn!=){printf("No\n");continue;}
if(g%k==&&mx-mn==(r-l)*k&&p<l)printf("Yes\n"),ny++;
else printf("No\n");
}
}
}
[线段树]洛谷P5278 算术天才⑨与等差数列的更多相关文章
- 线段树 洛谷P3932 浮游大陆的68号岛
P3932 浮游大陆的68号岛 题目描述 妖精仓库里生活着黄金妖精们,她们过着快乐,却随时准备着迎接死亡的生活. 换用更高尚的说法,是随时准备着为这个无药可救的世界献身. 然而孩子们的生活却总是无忧无 ...
- 区间连续长度的线段树——洛谷P2894 [USACO08FEB]酒店Hotel
https://www.luogu.org/problem/P2894 #include<cstdio> #include<iostream> using namespace ...
- BZOJ4373 算术天才⑨与等差数列 【线段树】*
BZOJ4373 算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍. 有一天,他给了你一个长度为n的序列,其中第i个数为a[i]. 他想考考你,每次他会给出询问l,r,k ...
- 【BZOJ4373】算术天才⑨与等差数列 [线段树]
算术天才⑨与等差数列 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 算术天才⑨非常喜欢和等 ...
- 【BZOJ4373】算术天才⑨与等差数列 线段树+set
[BZOJ4373]算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次他会给出询问l,r,k, ...
- 【线段树 集合hash】bzoj4373: 算术天才⑨与等差数列
hash大法好(@ARZhu):大数相乘及时取模真的是件麻烦事情 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次 ...
- bzoj 4373 算术天才⑨与等差数列
4373: 算术天才⑨与等差数列 Time Limit: 10 Sec Memory Limit: 128 MBhttp://www.lydsy.com/JudgeOnline/problem.ph ...
- JSOI2009 等差数列 和 算术天才⑨与等差数列 和 CH4302 Interval GCD
等差数列 为了检验学生的掌握情况,jyy布置了一道习题:给定一个长度为N(1≤N≤100,000)的数列,初始时第i个数为vi(vi是整数,−100,000≤vi≤100,000),学生们要按照jyy ...
- 洛谷3783 SDOI2017 天才黑客(最短路+虚树+边转点+线段树优化建图)
成功又一次自闭了 怕不是猪国杀之后最自闭的一次 一看到最短路径. 我们就能推测这应该是个最短路题 现在考虑怎么建图 根据题目的意思,我们可以发现,在本题中,边与边之间存在一些转换关系,但是点与点之间并 ...
随机推荐
- SpringBoot+SpringCloud+vue+Element开发项目——集成Druid数据源
添加依赖 pom.xml <!--druid--> <dependency> <groupId>com.alibaba</groupId> <ar ...
- TCP_Wrappers基础知识介绍
1. TCP_Wrappers基础知识介绍 TCP_Wrappers是在 Solaris, HP_UX以及 Linux中广泛流行的免费软件.它被设计为一个介于外来服务请求和系统服务回应的中间处理软件. ...
- (Linux基础学习)第六章:查询与修改系统的本地化(locale)与键盘布局的设置(locelectl)
第1节:可查询与修改系统的本地化(locale)与键盘布局的设置[root@centos7 ~]# localectl System Locale: LANG=en_US.UTF-8 VC Keyma ...
- C++(四十三) — 函数模板机制
1.普通函数与模板函数调用原则 函数模板可以像普通函数一样被重载: 当函数模板和普通函数都符合条件时,编译器优先考虑普通函数: 但如果函数模板产生一个更好的匹配,则选择函数模板: 可以通过空模板实参 ...
- linux系统编程之信号(五)
今天继续对信号进行学习,开始正入正题: sigaction函数: 安装信号之前我们已经学过一个函数:signal,它最早是在unix上出现的,它是对不可靠信号进行安装的,之后出现了可靠信号和实时信号, ...
- 01 浅谈c++及面向对象编程
参考链接: 学习完c++但是对c++面向对象编程还是比较模糊,现在花时间总体来总结一下: c++中的对象是使用类来定义的,下面先重点讲一下类的概念. 说到类就要先说一下类的三种特性:封装,继承,多态. ...
- oracle删除重复数据,只保留一条
比如,某个表要按照id和name重复,就算重复数据 delete from 表名 where rowid not in (select min(rowid) from 表名 group by id,n ...
- Spark Streaming的原理
Spark Streaming应用也是Spark应用,Spark Streaming生成的DStream最终也是会转化成RDD,然后进行RDD的计算,所以Spark Streaming最终的计算是RD ...
- c99的新功能
在ANSI的标准确立后,C语言的规范在一段时间内没有大的变动,然而C++在自己的标准化创建过程中继续发展壮大.<标准修正案一>在1994年为C语言创建了一个新标准,但是只修正了一些C89标 ...
- SIGAI机器学习第十九集 随机森林
讲授集成学习的概念,Bootstrap抽样,Bagging算法,随机森林的原理,训练算法,包外误差,计算变量的重要性,实际应用 大纲: 集成学习简介 Boostrap抽样 Bagging算法 随机森林 ...