算术天才⑨非常喜欢和等差数列玩耍。
有一天,他给了你一个长度为n的序列,其中第i个数为a[i]。
他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序后能否形成公差为k的等差数列。
当然,他还会不断修改其中的某一项。
为了不被他鄙视,你必须要快速并正确地回答完所有问题。
注意:只有一个数的数列也是等差数列。

第一行包含两个正整数n,m(1<=n,m<=300000),分别表示序列的长度和操作的次数。
第二行包含n个整数,依次表示序列中的每个数a[i](0<=a[i]<=10^9)。
接下来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的个数来进行解密。

这道题用检验累加和/平方和的方式水过了。。最后发现是质数太大,乘起来溢出了。。。。。。

调了我三天(蠢哭了)

 #include <cstdio>
#include <utility>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> ll;
//#define debug #ifdef debug
const LL maxn=, prime=1e9+;
#else
const LL maxn=3e5+, prime=1e9+;
#endif
LL n, m, cntyes;
//可以捆绑♂到一起,这样查询更新都方便
LL seg_sum[maxn*], seg_sqr[maxn*], maxm[maxn*], minm[maxn*];
LL flag, *seg, POS, L, R, v; inline LL max(LL x, LL y) { return x<y?y:x; }
inline LL min(LL x, LL y) { return x<y?x:y; }
inline void swap(LL &x, LL &y) { LL t=x; x=y; y=t; } void modify(LL now, LL l, LL r){ //其实可以四个一起修改
if (l>r||l>POS||r<POS) return;
if (l==r) {
if (flag==) maxm[now]=minm[now]=v;
if (flag==) seg_sum[now]=v, seg_sqr[now]=v*v%prime;
return;
}
LL mid=(l+r)>>;
modify(now<<, l, mid); modify(now<<|, mid+, r);
if (flag==){
maxm[now]=max(maxm[now<<], maxm[now<<|]);
minm[now]=min(minm[now<<], minm[now<<|]);
}
if (flag==) {
seg_sum[now]=(seg_sum[now<<]+seg_sum[now<<|])%prime;
seg_sqr[now]=(seg_sqr[now<<]+seg_sqr[now<<|])%prime;
}
} ll query(LL now, LL l, LL r){ //其实可以四个一起查询
if (l>r||l>R||r<L){
if (flag==) return make_pair(1e9, );
if (flag==) return make_pair(, );
}
if (l>=L&&r<=R){
if (flag==)
return make_pair(minm[now], maxm[now]);
if (flag==)
return make_pair(seg_sum[now], seg_sqr[now]);
}
LL mid=(l+r)>>;
ll pair1, pair2;
pair1=query(now<<, l, mid); pair2=query(now<<|, mid+, r);
if (flag==)
return make_pair(min(pair1.first, pair2.first),
max(pair1.second, pair2.second));
if (flag==)
return make_pair((pair1.first+pair2.first)%prime,
(pair1.second+pair2.second)%prime);
return make_pair(-, -);
} int main(){
scanf("%lld%lld", &n, &m);
LL value;
for (LL i=; i<=n; ++i){
scanf("%lld", &value);
flag=, POS=i, v=value;
modify(, , n);
flag=, POS=i, v=value;
modify(, , n);
}
LL op, x, y, l, r, k;
for (LL i=; i<m; ++i){
scanf("%lld", &op);
if (op==){
scanf("%lld%lld", &x, &y);
x^=cntyes, y^=cntyes;
flag=, POS=x, v=y;
modify(, , n);
flag=;
modify(, , n);
}
LL h, t, qsum, qsqr, vecsum, vecsqr;
if (op==){
scanf("%lld%lld%lld", &l, &r, &k);
l^=cntyes, r^=cntyes, k^=cntyes;
if (l==r){
++cntyes;
printf("Yes\n");
continue;
}
if (l>r) swap(l, r);
//查询最大最小值
flag=, L=l, R=r;
ll re=query(, , n);
//h:等差队列最小值,t:等差队列最大值
h=re.first, t=re.second;
if (k*(r-l)!=t-h){
printf("No\n"); continue;
}
//查询区间和
flag=, L=l, R=r;
re=query(, , n);
qsum=re.first, qsqr=re.second;
vecsum=(h+t)*(r-l+)/;
vecsum%=prime; //忘记模了。。
LL n=r-l+;
//计算等差数列的平方和 h:a1 k:d l=r时要特判!!!
vecsqr=(h*h%prime*n%prime+
(+n-)*n%prime*h%prime*k%prime)%prime+
k*k%prime*((n-)*n%prime*(*n-)/%prime);
vecsqr%=prime;
if (qsum==vecsum&&qsqr==vecsqr){
++cntyes;
printf("Yes\n");
}
else printf("No\n");
}
}
return ;
}

bzoj4373:算数天才与等差数列的更多相关文章

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

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

  2. [BZOJ4373]算术天才⑨与等差数列(线段树)

    [l,r]中所有数排序后能构成公差为k的等差数列,当且仅当: 1.区间中最大数-最小数=k*(r-l) 2.k能整除区间中任意两个相邻数之差,即k | gcd(a[l+1]-a[l],a[l+2]-a ...

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

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

  4. BZOJ4373 算术天才⑨与等差数列(线段树)

    看上去很难维护,考虑找一些必要条件.首先显然最大值-最小值=k*(r-l).然后区间内的数需要模k同余.最后区间内的数两两不同(k=0除外).冷静一下可以发现这些条件组合起来就是充分的了. 考虑怎么维 ...

  5. BZOJ4373 算术天才与等差数列 题解

    题目大意: 一个长度为n的序列,其中第i个数为a[i].修改一个点的值询问区间[l,r]内的数从小到大排序后能否形成公差为k的等差数列. 思路: 1.一段区间符合要求满足:(1)区间中的max-min ...

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

    设$pre[i]$表示第$i$个数上一次出现的位置,$d[i]=abs(a[i]-a[i+1])$. 用线段树维护区间内$a$的最小值.最大值,$pre$的最大值以及$d$的$\gcd$. 对于询问$ ...

  7. BZOJ4373: 算术天才⑨与等差数列(线段树 hash?)

    题意 题目链接 Sol 正经做法不会,听lxl讲了一种很神奇的方法 我们考虑如果满足条件,那么需要具备什么条件 设mx为询问区间最大值,mn为询问区间最小值 mx - mn = (r - l) * k ...

  8. bzoj4373 算术天才⑨与等差数列——线段树+set

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4373 一个区间有以 k 为公差的数列,有3个条件: 1.区间 mx - mn = (r-l) ...

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

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

随机推荐

  1. codeforces 633B B. A Trivial Problem(数论)

    B. A Trivial Problem time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  2. linux命令学习笔记(17):whereis 命令

    whereis命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b).man说明文件(参数-m)和 源代码文件(参数-s).如果省略参数,则返回所有信息. 和find相比,whereis查找的速度 ...

  3. Ubuntu 14.04开发环境

    安装ssh服务:sudo apt-get install openssh-server 安装vim:sudo apt-get install vim-gtk 安装gparted:sudo apt-ge ...

  4. oracle 12c 列式存储 ( In Memory 理论)

    随着Oracle 12c推出了in memory组件,使得Oracle数据库具有了双模式数据存放方式,从而能够实现对混合类型应用的支持:传统的以行形式保存的数据满足OLTP应用:列形式保存的数据满足以 ...

  5. Operating System-进程/线程内部通信-竞争条件(Race Conditions)

    从本文开始介绍进程间的通信,进程间通信遇到的问题以及方式其实和线程之间通信是一致的,所以进程间通信的所有理论知识都可以用在线程上,接下来的系列文章都会以进程之间的通信为模版进行介绍,本文主要内容: 进 ...

  6. SQL SERVER 中的*=和=*

    一.* =和= * 是在sql server2000中左连接,右连接的用法相当于left join 和right join,现在sql2005和2008默认是不支持的,可以设置兼容2000或2008 ...

  7. C#调试信息打印到输出窗口

    System.Diagnostics.Debug.WriteLine("aaaa");

  8. 【转】 Pro Android学习笔记(四二):Fragment(7):切换效果

    目录(?)[-] 利用setTransition 利用setCustomAnimations 通过ObjectAnimator自定义动态效果 程序代码的编写 利用fragment transactio ...

  9. web攻击之二:CSRF跨站域请求伪造

    CSRF是什么? (Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一,也被称为“One Click ...

  10. Java中“分号”引起的陷阱

    对于这类问题而言,难度不大,多半是由于我们有误操作引起的.但在查找问题所在的时候我们有可能需要花费一番功夫了. 实例一: package com.yonyou.test; /** * 测试类 * @a ...