算术天才⑨与等差数列

Time Limit: 10 Sec  Memory Limit: 128 MB
[Submit][Status][Discuss]

Description

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

Input

  第一行包含两个正整数n,m,分别表示序列的长度和操作的次数。
  第二行包含n个整数,依次表示序列中的每个数a[i]。
  接下来m行,每行一开始为一个数op,
  若op=1,则接下来两个整数x,y,表示把a[x]修改为y。
  若op=2,则接下来三个整数l,r,k,表示一个询问。
  在本题中,x,y,l,r,k都是经过加密的,都需要异或你之前输出的Yes的个数来进行解密。

Output

输出若干行,对于每个询问,如果可以形成等差数列,那么输出Yes,否则输出No。

Sample Input

  5 3
  1 3 2 5 6
  2 1 5 1
  1 5 4
  2 1 5 1

Sample Output

  No
  Yes

HINT

  1<=n,m<=300000, 0<=a[i]<=10^9, 1<=x<=n,0<=y<=10^9, 1<=l<=r<=n, 0<=k<=10^9

Solution

  显然,如果可以组成等差数列,首项必定是区间最小值。这样我们就知道了要求的等差数列的首项公差

  一个首先的想法就是:我们判断一下区间和是否等于所要求的等差数列的和

  但是这样显然是不够的,那么怎么办呢?我们试想:能否求出所要求的等差数列的平方和

  显然公差为 1 的时候平方和公式计算,剩下公差不是 1 的时候我们轻易推一下式子即可。

  

  那么我们只要用线段树维护一下:区间最小值、区间和、区间平方和即可,资磁单点修改

  正确性不会证明啊,但是满足的概率应该挺大的吧qwq

Code

 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef long long s64; const int ONE = ;
const int INF = 1e9+; int n, T;
s64 a[ONE];
int opt, x, y, d;
int num; struct power
{
s64 sumx, sumxx, minx;
}Node[ONE * ], res; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} void Renew(int i)
{
int a = i<<, b = i<<|;
Node[i].sumx = Node[a].sumx + Node[b].sumx;
Node[i].sumxx = Node[a].sumxx + Node[b].sumxx;
Node[i].minx = min(Node[a].minx, Node[b].minx);
} void Build(int i, int l, int r)
{
Node[i].minx = INF;
if(l == r)
{
Node[i].minx = a[l];
Node[i].sumx = a[l];
Node[i].sumxx = a[l] * a[l];
return;
} int mid = l + r >> ;
Build(i<<, l, mid); Build(i<<|, mid+, r);
Renew(i);
} void Update(int i, int l, int r, int L, s64 x)
{
if(l > r) return;
if(L == l && l == r)
{
Node[i].minx = x;
Node[i].sumx = x;
Node[i].sumxx = x * x;
return;
} int mid = l + r >> ;
if(L <= mid) Update(i<<, l, mid, L, x);
else Update(i<<|, mid+, r, L, x);
Renew(i);
} void Query(int i, int l, int r, int L, int R)
{
if(L <= l && r <= R)
{
res.minx = min(res.minx, Node[i].minx);
res.sumx += Node[i].sumx;
res.sumxx += Node[i].sumxx;
return;
} int mid = l + r >> ;
if(L <= mid) Query(i<<, l, mid, L, R);
if(mid+ <= R) Query(i<<|, mid+, r, L, R);
} s64 Calc_sumx(s64 a0, s64 n, s64 d)
{
s64 an = a0 + (n-) * d;
return (a0 + an) * n / ;
} s64 Calc_sumxx(s64 a0, s64 n, s64 d)
{
s64 item1 = n * a0 * a0;
s64 item2 = * a0 * d * n * (n-) / ;
s64 item3 = d * d * (n * (n+) * (*n+) / - n*n);
return item1 + item2 + item3;
} int main()
{
n = get(); T = get();
for(int i=; i<=n; i++)
a[i] = get();
Build(, , n); while(T--)
{
opt = get();
x = get() ^ num; y = get() ^ num; if(opt == )
{
Update(, , n, x, y);
continue;
}
else
{
d = get() ^ num;
res.minx = INF;
res.sumx = res.sumxx = ;
Query(, , n, x, y); if(res.sumx == Calc_sumx(res.minx, y-x+, d))
if(res.sumxx == Calc_sumxx(res.minx, y-x+, d))
{
printf("Yes\n");
num++;
continue;
} printf("No\n");
}
} }

【BZOJ4373】算术天才⑨与等差数列 [线段树]的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ 4373 算术天才⑨与等差数列 线段树+set(恶心死我了)

    mdzz,这道题重构了4遍,花了一个晚上... 满足等差数列的条件: 1. 假设min是区间最小值,max是区间最大值,那么 max-min+k(r−l) 2. 区间相邻两个数之差的绝对值的gcd=k ...

  6. BZOJ 4373算术天才⑨与等差数列(线段树)

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

  7. BZOJ 4373: 算术天才⑨与等差数列 线段树

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

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

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4373 能形成公差为k的等差数列的条件:mx-mn=k*(r-l) && 差分 ...

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

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

随机推荐

  1. # 团队作业MD

    队员姓名与学号 051501124 王彬(组长) 111500206 赵畅 031602215 胡展瑞 031602320 李恒达 031602131 佘岳昕 031602431 王源 0316022 ...

  2. 第三章——供机器读取的数据(CSV与JSON)

    本书使用的文件.代码:https://github.com/huangtao36/data_wrangling 机器可读(machine readable)文件格式: 1.逗号分隔值(Comma-Se ...

  3. lintcode-144-交错正负数

    144-交错正负数 给出一个含有正整数和负整数的数组,重新排列成一个正负数交错的数组. 注意事项 不需要保持正整数或者负整数原来的顺序. 样例 给出数组[-1, -2, -3, 4, 5, 6],重新 ...

  4. Unity3d学习日记(二)

      跟着教程做让背景可以滚动起来并添加了背景的粒子特效,加入了敌机.   ctrl攻击,↑↓←→移动,Game Over后按R重新开始游戏.   Space Shooter游戏地址:http://ya ...

  5. Sqoop 1.4.6 安装配置

    配置环境变量 # SQOOP SQOOP_HOME=/home/hadoop/development/src/sqoop-1.4.6-cdh5.6.0 PATH=$PATH:$SQOOP_HOME/b ...

  6. 【Linux】- rm命令

    Linux rm命令用于删除一个文件或者目录. 语法 rm [options] name... 参数: -i 删除前逐一询问确认. -f 即使原档案属性设为唯读,亦直接删除,无需逐一确认. -r 将目 ...

  7. mysql中删除重复记录,并保留重复数据中的一条数据的SQL语句

    正好想写一条删除重复语句并保留一条数据的SQL,网上查了一部分资料写的很详细,但还是在这里写下自己的理解,以遍后续学习 .如下: 表字段和数据: SQL语句: [sql] view plain cop ...

  8. C++面向对象编程,继承,数据抽象,动态绑定

    派生类(derived class)能够继承基类(base class )定义的成员: 1).派生类可以无需改变而使用那些与派生类具体特性不相关的操作 2).可以重新定义那些与派生类相关的成员函数,将 ...

  9. Redis 基础:Redis 简介及安装

    Remote Dictionary Server(Redis)是一个由Salvatore Sanfilippo写的key-value存储系统.Redis是一个开源的使用ANSI C语言编写.遵守BSD ...

  10. BZOJ4835 遗忘之树

    点分树上的某个点和其某个子树在原树中的连接方式一般来说可以是由该点连向子树内任意一点,这样方案数即为所有子树大小之积.但有一种特殊情况是连接某点后导致编号最小的重心更换,只要去掉这种就行了,具体地可以 ...