[线段树]洛谷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 天才黑客(最短路+虚树+边转点+线段树优化建图)
成功又一次自闭了 怕不是猪国杀之后最自闭的一次 一看到最短路径. 我们就能推测这应该是个最短路题 现在考虑怎么建图 根据题目的意思,我们可以发现,在本题中,边与边之间存在一些转换关系,但是点与点之间并 ...
随机推荐
- flutter isolate demo
main.dart import 'package:flutter/material.dart'; import 'package:flutter_isolate/flutter_isolate.da ...
- 2019年北航OO第三次博客总结
一.JML语言理论基础及其工具链 1. JML语言理论基础 JML是用于对Java程序进行规格化设计的一种表示语言,是一种行为接口规格语言(Behavior Interface Specificati ...
- css实现 textarea 高度自适应
此textarea非彼textarea ,有经验的老司机们应该知道html标签contenteditable这个属性. 利用此属性使当前的标签成为可以输入的状态,等同于输入框. 演示地址:https: ...
- 浅谈React编程思想
React是Facebook推出的面向视图层开发的一个框架,用于解决大型应用,包括如何很好地管理DOM结构,是构建大型,快速Web app的首选方式. React使用JavaScript来构建用户界面 ...
- XML 约束
XML约束 一.约束 约束:规定 xml 文档的书写规则 要求: 1.能够在 xml 中引入约束文档 2.能够简单的读懂约束文档 分类: 1.DTD:一种简单的约束技术(后缀.dtd) 2.Schem ...
- AutoMapper 初次使用心得
本例以asp.net webform为例: 结构: 主要代码:AutoMapperConfig 类 public class AutoMapperConfig { public static void ...
- javascript 四舍五入; js 四舍五入
方法 Math.round round() 方法可把一个数字舍入为最接近的整数. 对于 0.5,该方法将进行上舍入. 例如,3.5 将舍入为 4,而 -3.5 将舍入为 -3. Math.round( ...
- MyCAT+MySQL搭建高可用企业级数据库集群视频课程
原文地址:https://www.guangboyuan.cn/mycatmysql%E6%90%AD%E5%BB%BA%E9%AB%98%E5%8F%AF%E7%94%A8%E4%BC%81%E4% ...
- Flink源码阅读(一)——Flink on Yarn的Per-job模式源码简析
一.前言 个人感觉学习Flink其实最不应该错过的博文是Flink社区的博文系列,里面的文章是不会让人失望的.强烈安利:https://ververica.cn/developers-resource ...
- UniChat-软件工程小组-第一次作业-选题
软件工程小组项目文档 小组成员:赵有为.张天善.宋春雨.郭凯璐.孙楠.冯韵瑶 Uni-Chat项目文档 需求分析Need 日常生活中我们在使用Ubuntu等系统时都会因为QQ等聊天工具对基于Lin ...