[线段树]洛谷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 天才黑客(最短路+虚树+边转点+线段树优化建图)
成功又一次自闭了 怕不是猪国杀之后最自闭的一次 一看到最短路径. 我们就能推测这应该是个最短路题 现在考虑怎么建图 根据题目的意思,我们可以发现,在本题中,边与边之间存在一些转换关系,但是点与点之间并 ...
随机推荐
- 【开发笔记】- Java读取properties文件的五种方式
原文地址:https://www.cnblogs.com/hafiz/p/5876243.html 一.背景 最近,在项目开发的过程中,遇到需要在properties文件中定义一些自定义的变量,以供j ...
- Ajax + PHP 的用法以及遇见的问题
由于自己是个php小白,所以新知识点都要自己去不断的试验和摸索. 分享下自己用php + ajax交互的用法和问题. 前端代码: $.ajax({ type: "POST", da ...
- laravel——表操作集成操作
背景:通过判断不同的请求参数,返回不同的需要的数据 一.准备工作: 数据库新建一个表 DROP TABLE IF EXISTS `tb_category2`; CREATE TABLE IF NOT ...
- Mybatis中传递多个参数的方法总结
一.单个参数: public List<XXBean> getXXBeanList(String xxCode); <select id="getXXXBeanList&q ...
- systemd_journal_no_entries问题解决
问题: #journalctl Journal file /var/log/journal/410/system@0.journal~ uses an unsupported feature, ign ...
- Linux命令——rsync
参考:Rsync (Remote Sync): 10 Practical Examples of Rsync Command in Linux How to Sync Files/Directorie ...
- sql的匹配和正则表达式
1. 匹配:like 关键字 #假设存在表 my_test_copy select * from my_test_copy; 则使用like关键词匹配:注意下划线 '_'和百分号 '%' # 下划线' ...
- Linux GRUB手动安装方法详解
需要手工安装 GRUB 主要有两种情况: Linux 系统原先不是使用 GRUB 作为引导程序而现在想要使用 GRUB 来作为引导程序: MBR 中的引导程序被覆盖,需要在 MBR 中重新安装 GRU ...
- css背景雪碧图等
1.背景图 雪碧图技术 要设置背景,是要设置在某个盒子上 <!doctype html> <html lang="en"> <head> < ...
- 用java刷剑指offer(数字在排序数组中出现的次数)
题目描述 统计一个数字在排序数组中出现的次数. 牛客网链接 java代码 //看见有序就用二分法 public class Solution { public int GetNumberOfK(int ...