//被标题吸引进来,无论如何都要切出来

题目大意

给你一个长度为n的序列,有m个操作,写一个程序支持以下两个操作:
1. 修改一个值
2. 给出三个数l,r,k,询问:如果把区间[l,r]的数从小到大排序,能否形成公差为k的等差数列。
强制在线

数据范围

n,m≤300000 0≤k,a[i]≤ 109 10^9

分析

首先特判k=0和l=r的情况。

然后考虑不满足上面两个条件的情况。
直接维护区间等差数列显然很难,那么考虑一下:如果区间[l,r] (l < r)排序后能形成公差为k(k>0)的等差数列,要满足什么条件?
1. 很显然,假设min是区间最小值,max是区间最大值,那么 min+k(r−l)=max min+k(r-l)=max
2. 区间相邻两个数之差的绝对值的gcd=k,可以自行脑补一下
3. 区间没有重复的数

维护区间信息

上述的前两个条件可以直接用线段树维护。
现在看第3个条件。
首先,序列出现过的值最多只有600000种,所以可以对于每个值开一个set,对应的id用一个map存起来。
然后维护一个pre[i],表示当前a[i]这个值,在i前面最后一次出现的位置。那么满足第3个条件,当且仅当区间[l,r]的pre的最大值小于l。这个也是用线段树维护。
然后看修改操作:在set上找前一个数、后一个数,然后修改相应的值。
时间复杂度 O(nlogn) O(nlogn),要注意优化常数。

/**************************************************************Problem: 4373User: worldwideLanguage: C++Result: AcceptedTime:6148 msMemory:53008 kb
****************************************************************/#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>#define id it->secondusing namespace std;const int maxn=300005,maxt=1048578,maxm=600005;typedef long long LL;int n,m,cnt,Min[maxt],Max[maxt],a[maxn],Max_pre[maxt],pre[maxn],next[maxn],Gcd[maxt],tot,l,r;int mininum,maxinum,G;bool flag;char c;map <int,int> num;set <int> tree[maxm];int read()
{for (c=getchar();c<'0' || c>'9';c=getchar());int x=c-48;for (c=getchar();c>='0' && c<='9';c=getchar()) x=x*10+c-48;return x;
}int gcd(int x,int y)
{if (x==0) return y;if (y==0) return x;return gcd(y,x%y);
}void init(int l,int r,int x)
{if (l==r){Min[x]=Max[x]=a[l]; Max_pre[x]=pre[l];if (l<n) Gcd[x]=abs(a[l]-a[l+1]);else Gcd[x]=1;return;}int mid=l+r>>1;init(l,mid,x<<1); init(mid+1,r,x<<1|1);Min[x]=min(Min[x<<1],Min[x<<1|1]);Max[x]=max(Max[x<<1],Max[x<<1|1]);Max_pre[x]=max(Max_pre[x<<1],Max_pre[x<<1|1]);Gcd[x]=gcd(Gcd[x<<1],Gcd[x<<1|1]);
}void change_pre(int l,int r,int g,int New,int x)
{if (l==r){Max_pre[x]=pre[l]=New;return;}int mid=l+r>>1;if (g<=mid) change_pre(l,mid,g,New,x<<1);else change_pre(mid+1,r,g,New,x<<1|1);Max_pre[x]=max(Max_pre[x<<1],Max_pre[x<<1|1]);
}void change_a(int l,int r,int g,int x)
{if (l==r){Min[x]=Max[x]=a[l];return;}int mid=l+r>>1;if (g<=mid) change_a(l,mid,g,x<<1);else change_a(mid+1,r,g,x<<1|1);Min[x]=min(Min[x<<1],Min[x<<1|1]);Max[x]=max(Max[x<<1],Max[x<<1|1]);Max_pre[x]=max(Max_pre[x<<1],Max_pre[x<<1|1]);
}void change_gcd(int l,int r,int g,int x)
{if (l==r){Gcd[x]=abs(a[l]-a[l+1]);return;}int mid=l+r>>1;if (g<=mid) change_gcd(l,mid,g,x<<1);else change_gcd(mid+1,r,g,x<<1|1);Gcd[x]=gcd(Gcd[x<<1],Gcd[x<<1|1]);
}void query(int l,int r,int a,int b,int x)
{if (l==a && r==b){if (Max_pre[x]>=l) flag=1;if (Min[x]<mininum) mininum=Min[x];if (Max[x]>maxinum) maxinum=Max[x];return;}int mid=l+r>>1;if (b<=mid) query(l,mid,a,b,x<<1);else if (a>mid) query(mid+1,r,a,b,x<<1|1);else{query(l,mid,a,mid,x<<1); query(mid+1,r,mid+1,b,x<<1|1);}
}void query_gcd(int l,int r,int a,int b,int x)
{if (l==a && r==b){G=gcd(G,Gcd[x]);return;}int mid=l+r>>1;if (b<=mid) query_gcd(l,mid,a,b,x<<1);elseif (a>mid) query_gcd(mid+1,r,a,b,x<<1|1);else{query_gcd(l,mid,a,mid,x<<1); query_gcd(mid+1,r,mid+1,b,x<<1|1);}
}int main()
{n=read(); m=read();for (int i=1;i<=n;i++){a[i]=read();map <int,int> ::iterator it=num.find(a[i]);if (it==num.end()){num.insert(make_pair(a[i],++tot));tree[tot].insert(i);pre[i]=0;}else{tree[id].insert(i);set <int> ::iterator ii=tree[id].find(i); ii--;pre[i]=*ii; next[*ii]=i;}}init(1,n,1);while (m--){int op=read();if (op==1){int x=read()^cnt,y=read()^cnt;if (a[x]==y) continue;map <int,int> ::iterator it=num.find(a[x]);set <int> ::iterator ii=tree[id].find(x);if (pre[x]>0){next[pre[x]]=next[x];if (next[x]>0) change_pre(1,n,next[x],pre[x],1);}else if (next[x]>0) change_pre(1,n,next[x],0,1);tree[id].erase(ii);it=num.find(y);if (it==num.end()){num.insert(make_pair(y,++tot));tree[tot].insert(x);pre[x]=next[x]=0;}else{tree[id].insert(x);ii=tree[id].find(x);if (ii!=tree[id].begin()){ii--;next[x]=next[*ii];if (next[x]>0) change_pre(1,n,next[x],x,1);next[*ii]=x;pre[x]=*ii;}}a[x]=y;change_a(1,n,x,1);if (x>1) change_gcd(1,n,x-1,1);if (x<n) change_gcd(1,n,x,1);}else{l=read()^cnt; r=read()^cnt; int k=read()^cnt;if (l==r){printf("Yes\n"); cnt++; continue;}mininum=(int)1e9; maxinum=flag=0;query(1,n,l,r,1);if (!k){if (mininum==maxinum){printf("Yes\n"); cnt++;}else printf("No\n");continue;}G=k;query_gcd(1,n,l,r-1,1);if (flag || mininum+(LL)k*(r-l)!=maxinum || G<k){printf("No\n");}else{printf("Yes\n"); cnt++;}}}return 0;
}

[bzoj4373]算术天才⑨与等差数列相关推荐

  1. BZOJ4373: 算术天才⑨与等差数列

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

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

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

  3. 【BZOJ4373】算术天才⑨与等差数列

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

  4. P5278 算术天才⑨与等差数列 题解

    一道不错的题目,只不过能被 hash 和维护若干次方和通过,本篇讲正解. 考虑一个乱序序列重排后是等差数列的一些条件(设区间 [ l , r ] [l,r] [l,r],公差为 d d d): 数列最 ...

  5. 等差素数咧 c语言,等差数列

    1354. 等差数列2021-05-24 20:06:01 预处理出双平方数集合 枚举双平方数中的一对数作为等差数列的首项和第二项 剪枝: 计算出当前等差数列的末项,last=x+(n-1)*d比双平 ...

  6. 暑假训练-义乌(7.8-7.15)

    暑假训练 模拟赛 图表 数据 7.8(lxl) 7.9(lxl) 7.10(lxl) 7.11(lxl) 7.12(wls) 7.13(wls) 7.14(wls) 7.15(lfds) 训练 数据结 ...

  7. [生存志] 第117节 九章算术均徭赋

            九章算术均徭赋                  贾谊在27岁时向汉文帝进献的<治安策>一文,洋洋洒洒6844个字,写了汉帝国开国30年时的九件让他忧伤难过的事情,所谓『可 ...

  8. 开放性:你可能没听说过的终极大挑战(开放性既是驱动探索智能的力量之一,也可能直接就是AI本身的组成部分)

    编者注:更多关于人工智能信息请关注2018年4月10-13日人工智能北京大会.2018年1月26日之前购买门票享有早期最惠价格 . 人工智能(Artificial Intelligence, AI)是 ...

  9. #3316. baka

    题目描述 Worldwide_D最近沉迷东方. 数学课上,Worldwide_D在研究对数,然后渐渐睡着了.他梦见自己躺在幻想乡的雾之湖边,听见旁边有两个妖精在对话,原来是Cirno和Daiyouse ...

最新文章

  1. Promise--感性认知
  2. A题 Go! Fun游长三角 2021年第一届长三角高校数学建模竞赛
  3. Python的模块化编程
  4. redis分布式锁java代码_基于redis实现分布式锁
  5. linux强实时,强实时性Linux内核的研究与设计
  6. C#计算程序的运行时间
  7. 系统设置参数说明11
  8. 常用脚本--在线重建或重整实例下所有索引
  9. 求100~200间的所有素数
  10. 第五章 调优案列分析与实战(待续)
  11. tplink 服务器未响应,详解win10安装tplink网卡免驱版无法用关键操作方法
  12. python3.6+Appium实现手机微信自动回复
  13. 网站通行证的交互设计分析
  14. (译)如何制作一个类似tiny wings的游戏:第二部分(完) - 子龙山人 ...
  15. 2016集训队论文吉如一
  16. 分享一款实用的太阳能充电电路(室内光照可用)
  17. 数据结构之SWUSTOJ1038: 顺序表中重复数据的删除
  18. nltk词性标注的涵义
  19. 孟子:生于忧患,死于安乐
  20. Ubuntu 16.04系统安装VS Code流程详解

热门文章

  1. 【链塔DApp日报】BDI指数增长5%,Chintai 24h交易额增长251%
  2. oracle 存储过程select into,01. 把存储过程结果集SELECT INTO到临时表(示例代码)
  3. 加班多年,你敢说没遇过这种破事我也是服!
  4. Android模拟器启动慢解决办法
  5. python好就业么_Python语言就业前景怎么样?好吗?
  6. 系统服务器可以关机吗,服务器主机可以关机吗
  7. 阿里 weex--前端整合开源框架(记录)
  8. linux远程登录管理工具
  9. ArrayDeque底层实现
  10. Win10系统下CAD2009 VBA加滚轮