题目描述

算术天才⑨非常喜欢和等差数列玩耍。 有一天,他给了你一个长度为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 算术天才⑨与等差数列的更多相关文章

  1. 线段树 洛谷P3932 浮游大陆的68号岛

    P3932 浮游大陆的68号岛 题目描述 妖精仓库里生活着黄金妖精们,她们过着快乐,却随时准备着迎接死亡的生活. 换用更高尚的说法,是随时准备着为这个无药可救的世界献身. 然而孩子们的生活却总是无忧无 ...

  2. 区间连续长度的线段树——洛谷P2894 [USACO08FEB]酒店Hotel

    https://www.luogu.org/problem/P2894 #include<cstdio> #include<iostream> using namespace ...

  3. BZOJ4373 算术天才⑨与等差数列 【线段树】*

    BZOJ4373 算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍. 有一天,他给了你一个长度为n的序列,其中第i个数为a[i]. 他想考考你,每次他会给出询问l,r,k ...

  4. 【BZOJ4373】算术天才⑨与等差数列 [线段树]

    算术天才⑨与等差数列 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 算术天才⑨非常喜欢和等 ...

  5. 【BZOJ4373】算术天才⑨与等差数列 线段树+set

    [BZOJ4373]算术天才⑨与等差数列 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次他会给出询问l,r,k, ...

  6. 【线段树 集合hash】bzoj4373: 算术天才⑨与等差数列

    hash大法好(@ARZhu):大数相乘及时取模真的是件麻烦事情 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次 ...

  7. bzoj 4373 算术天才⑨与等差数列

    4373: 算术天才⑨与等差数列 Time Limit: 10 Sec  Memory Limit: 128 MBhttp://www.lydsy.com/JudgeOnline/problem.ph ...

  8. JSOI2009 等差数列 和 算术天才⑨与等差数列 和 CH4302 Interval GCD

    等差数列 为了检验学生的掌握情况,jyy布置了一道习题:给定一个长度为N(1≤N≤100,000)的数列,初始时第i个数为vi(vi是整数,−100,000≤vi≤100,000),学生们要按照jyy ...

  9. 洛谷3783 SDOI2017 天才黑客(最短路+虚树+边转点+线段树优化建图)

    成功又一次自闭了 怕不是猪国杀之后最自闭的一次 一看到最短路径. 我们就能推测这应该是个最短路题 现在考虑怎么建图 根据题目的意思,我们可以发现,在本题中,边与边之间存在一些转换关系,但是点与点之间并 ...

随机推荐

  1. 各种变异绕过XSS过滤器

    各种变异绕过XSS过滤器(Various variations bypass the XSS filter ) 文章来自:https://www.cnblogs.com/iAmSoScArEd/p/1 ...

  2. Jmeter学习笔记(十五)——常用的4种参数化方式

    一.Jmeter参数化概念 当使用JMeter进行测试时,测试数据的准备是一项重要的工作.若要求每次迭代的数据不一样时,则需进行参数化,然后从参数化的文件中来读取测试数据. 参数化是自动化测试脚本的一 ...

  3. HashMap的put()与扩容

    1. put() final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { HashMap.Nod ...

  4. 208道Java常见的面试题

    一.Java 基础 1.JDK 和 JRE 有什么区别? JRE=JVM+各种基础类库+java类库(String\System) JDK>JRE>JVM JRE:是java运行时环境  ...

  5. (比赛)C - 小Q系列故事——最佳裁判(水题)

    C - 小Q系列故事——最佳裁判 Time Limit:200MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Des ...

  6. PM2 监控 Spring Boot 项目运行

    更多 PM2 的用法介绍请参考: PM2简易使用手册 - 掘金 由于 PM2 通常都用于 node 应用, 所以 exec_mode 应写为 fork, 其中最重要的是 args, -jar 和 ja ...

  7. 交叉编译openssl1.1.1a

    ​ 交叉编译openssl1.1.1a的时候遇到的问题,记录一下,方便下次查找 一.下载源码 1.打开openssl官网,下载openssl-1.1.1.tar.gz源码包. 2.执行下面的命令解压源 ...

  8. Python 网络爬虫的常用库汇总

    爬虫的编程语言有不少,但 Python 绝对是其中的主流之一.下面就为大家介绍下 Python 在编写网络爬虫常常用到的一些库. 请求库:实现 HTTP 请求操作 urllib:一系列用于操作URL的 ...

  9. 安装配置KVM虚拟化

    安装KVM虚拟化 KVM需要硬件⽀持, 所以需要开启虚拟化⽀持 硬件设备直接在BIOS设置开启CPU虚拟化 个⼈电脑同样进⼊BIOS开启虚拟化⽀持 VM需要找到对应虚拟机开启对应的VT-EPT虚拟化技 ...

  10. Vuex状态管理总结

    一.什么是 Vuex 1.Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 2.Vuex 采用集中式存储和管理应用中所有组件的状态 3.Vuex 应用的核心是 store(仓库)-- 包 ...