hash大法好(@ARZhu);大数相乘及时取模真的是件麻烦事情

Description

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

Input

第一行包含两个正整数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的个数来进行解密。

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

题目分析

动态询问区间是否为「等差数列」。出题人用线段树维护了区间最小;区间gcd;区间……等等一系列标记。

然而HZQ给出了一个吊打出题人的做法:线段树hash。

注意到询问的区间可以视作集合形式,与顺序无关。于是便可以快速地集合hash。

具体来说用线段树维护区间最小值(用于寻找等差数列首项);区间立方和(由费马大定理得立方和不容易被卡;不过在这题出题人并没有恶意卡平方哈希)

问题就在于如何快速验证;换句话说就是计算询问的等差数列的hash值$x^3+(x+k)^3+(x+2*k)^3+...+(x+(n-1)*k)^3$其中$n$为序列长度

把式子按照指数展开,就可以愉快地$O(1)$计算数列答案了。我才没有暴力展开算了1h什么都没算出来

 #include<bits/stdc++.h>
typedef long long ll;
const ll MO = 1e9+;
const int INF = 2e9;
const int maxn = ; int n,m,preans;
ll mn[maxn<<],f[maxn<<]; int read()
{
char ch = getchar();
int num = ;
bool fl = ;
for (; !isdigit(ch); ch = getchar())
if (ch=='-') fl = ;
for (; isdigit(ch); ch = getchar())
num = (num<<)+(num<<)+ch-;
if (fl) num = -num;
return num;
}
ll qmi(ll a, ll b)
{
ll ret = ;
while (b)
{
if (b&) ret = ret*a%MO;
a = a*a%MO, b >>= ;
}
return ret;
}
void pushup(int rt)
{
mn[rt] = std::min(mn[rt<<], mn[rt<<|]);
f[rt] = (f[rt<<]+f[rt<<|])%MO;
}
void build(int rt, int l, int r)
{
mn[rt] = INF;
if (l==r){
mn[rt] = f[rt] = read();
f[rt] = 1ll*f[rt]*f[rt]%MO*f[rt]%MO;
return;
}
int mid = (l+r)>>;
build(rt<<, l, mid), build(rt<<|, mid+, r);
pushup(rt);
}
void update(int rt, int l, int r, int pos, ll c)
{
if (l==r){
f[rt] = c*c%MO*c%MO, mn[rt] = c;
return;
}
int mid = (l+r)>>;
if (pos <= mid) update(rt<<, l, mid, pos, c);
else update(rt<<|, mid+, r, pos, c);
pushup(rt);
}
int queryMn(int rt, int L, int R, int l, int r)
{
if (L <= l&&r <= R) return mn[rt];
int mid = (l+r)>>, ret = INF;
if (L <= mid)
ret = queryMn(rt<<, L, R, l, mid);
if (R > mid) ret = std::min(ret, queryMn(rt<<|, L, R, mid+, r));
return ret;
}
ll query(int rt, int L, int R, int l, int r)
{
if (L <= l&&r <= R) return f[rt]%MO;
int mid = (l+r)>>;
ll ret = ;
if (L <= mid) ret = query(rt<<, L, R, l, mid);
if (R > mid) ret += query(rt<<|, L, R, mid+, r);
return ret%MO;
}
ll calc(ll x, ll n, ll k)
{
ll ret = n*x%MO*x%MO*x%MO, pos = 1ll*n*(n-)%MO*qmi(, MO-)%MO;
ret += ((k*k%MO*k%MO*pos%MO*pos%MO+3*k%MO*x%MO*x%MO*pos%MO)%MO+k*x%MO*k%MO*(2*n-1)%MO*pos%MO)%MO;
return ret%MO;          //时刻记得要取模!
}
int main()
{
// freopen("4373.in","r",stdin);
// freopen("4373.out","w",stdout);
n = read(), m = read();
build(, , n);
for (int i=; i<=m; i++)
{
int opt = read();
if (opt==){
int x = read()^preans, y = read()^preans;
update(, , n, x, y);
}else{
int l = read()^preans, r = read()^preans, k = read()^preans, lens = (r-l+);
int st = queryMn(, l, r, , n);
ll sum = query(, l, r, , n);
if (calc(st, lens, k)==sum) preans++, puts("Yes");
else puts("No");
}
}
return ;
}

END

【线段树 集合hash】bzoj4373: 算术天才⑨与等差数列的更多相关文章

  1. [线段树]洛谷P5278 算术天才⑨与等差数列

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. __slots__,__doc__,__module__,__class__.__call__

    __slots__ 1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)2.引子:使用点来访问属性本质就是在访问类或 ...

  2. 如何使用LESS 深度定制Bootstrap

    一.LESS是什么? Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量.Mixin.函数等特性,使 CSS 更易维护和扩展. 中文介绍:http://lesscss.cn/ 有 ...

  3. 【Codeforces1111D_CF1111D】Destroy the Colony(退背包_组合数学)

    题目: Codeforces1111D 翻译: [已提交至洛谷CF1111D] 有一个恶棍的聚居地由几个排成一排的洞穴组成,每一个洞穴恰好住着一个恶棍. 每种聚居地的分配方案可以记作一个长为偶数的字符 ...

  4. python学习之IO:

    输入输出兼程IO操作,有同步(速度不匹配时四等)和异步(轮询和消息通知,复杂而高效) 一 文件操作函数: 文件打开:f=open("文件路径“,“操作类型 r/rb/w/a”,"编 ...

  5. 174. 删除链表中倒数第n个节点

    描述 笔记 数据 评测 给定一个链表,删除链表中倒数第n个节点,返回链表的头节点. 注意事项 链表中的节点个数大于等于n 您在真实的面试中是否遇到过这个题? Yes 样例 给出链表1->2-&g ...

  6. SpringBoot 2.x (12):整合Elasticsearch

    Elasticsearch:一个优秀的搜索引擎框架 搜索方面最基本的是SQL的like语句 进一步的有Lucene框架 后来有企业级的Solr框架 而Elasticsearch框架尤其适合于数据量特别 ...

  7. php调用c# webservice方法

    第一次用,通过,还没深入了解. 首先在php.ini中启用extension=php_soap.dll,重启apache. $Client=new SoapClient("url?wsdl& ...

  8. Vue.js - day7

    使用mui的tab-top-webview-main完成分类滑动栏 兼容问题 和 App.vue 中的 router-link 身上的类名 mui-tab-item 存在兼容性问题,导致tab栏失效, ...

  9. HTML5+CSS3新增内容总结!!!!!绝对干货

    说到H5C3会不会觉得东西好多啊,今天就整理了一份总结性的内容: CSS3选择器有哪些?答:属性选择器.伪类选择器.伪元素选择器.CSS3新特性有哪些?答:1.颜色:新增RGBA,HSLA模式 文字阴 ...

  10. JavaScprit30-5 学习笔记

    最近忙这忙那...好久没看视频学习了...但是该学的还是要学. 这次要实现的效果是利用 flex 的 特性 来实现 可伸缩的图片墙演示 页面的展示...: 效果挺炫酷啊... 那么就来总结一下 学到了 ...