BZOJ 4373

这道题可以用哈希...感觉哈希真的是很万能的一种方法...

我们可以用线段树记录一下[l,r]这个区间的数的和,数的平方和,那么对于一个询问,我们算一下这个等差序列的和与平方和是否与这个区间的相等,如果相等我们就认为可以构成等差数列。

感觉这种哈希的思想很巧妙,这种思想还是要多尝试,多应用

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 #define maxn 300005
  6 typedef unsigned long long ull;
  7 struct tree
  8 {
  9     int l,r,k;
 10     ull sum,psum;
 11 }t[maxn*4];
 12 int n,m,cnt;
 13 ull a[maxn];
 14
 15 inline int read(void)
 16 {
 17     int x=0;
 18     char ch=getchar();
 19     while (ch>‘9‘||ch<‘0‘) ch=getchar();
 20     while (ch>=‘0‘&&ch<=‘9‘)
 21     {
 22         x=x*10+ch-‘0‘;
 23         ch=getchar();
 24     }
 25     return x;
 26 }
 27
 28 void build(int x,int l,int r)
 29 {
 30     t[x].l=l;t[x].r=r;
 31     if (l==r)
 32     {
 33         t[x].sum=a[l];
 34         t[x].psum=a[l]*a[l];
 35         t[x].k=a[l];
 36         return;
 37     }
 38     int mid=(l+r)>>1;
 39     build(2*x,l,mid);
 40     build(2*x+1,mid+1,r);
 41     t[x].k=min(t[2*x].k,t[2*x+1].k);
 42     t[x].sum=t[2*x].sum+t[2*x+1].sum;
 43     t[x].psum=t[2*x].psum+t[2*x+1].psum;
 44 }
 45
 46 void change(int x,int y,int z)
 47 {
 48     if (t[x].l==t[x].r)
 49     {
 50         t[x].sum=z;
 51         t[x].psum=(ull)z*z;
 52         t[x].k=z;
 53         return;
 54     }
 55     int mid=(t[x].l+t[x].r)>>1;
 56     if (y<=mid) change(2*x,y,z);
 57     else change(2*x+1,y,z);
 58     t[x].k=min(t[2*x].k,t[2*x+1].k);
 59     t[x].sum=t[2*x].sum+t[2*x+1].sum;
 60     t[x].psum=t[2*x].psum+t[2*x+1].psum;
 61 }
 62
 63 tree query(int x,int l,int r)
 64 {
 65     if (t[x].l==l&&t[x].r==r) return t[x];
 66     int mid=(t[x].l+t[x].r)>>1;
 67     if (l>mid) return query(2*x+1,l,r);
 68     else if (r<=mid) return query(2*x,l,r);
 69     else
 70     {
 71         tree t1=query(2*x,l,mid);
 72         tree t2=query(2*x+1,mid+1,r);
 73         tree t3;
 74         t3.k=min(t1.k,t2.k);
 75         t3.sum=t1.sum+t2.sum;
 76         t3.psum=t1.psum+t2.psum;
 77         return t3;
 78     }
 79 }
 80
 81 int main()
 82 {
 83     n=read();m=read();
 84     for (int i=1;i<=n;i++) a[i]=read();
 85     build(1,1,n);
 86     for (int i=1;i<=m;i++)
 87     {
 88         int opt=read();
 89         if (opt==1)
 90         {
 91             int x=read()^cnt,y=read()^cnt;
 92             change(1,x,y);
 93         }
 94         if (opt==2)
 95         {
 96             int l=read()^cnt,r=read()^cnt,d=read()^cnt;
 97             ull L=r-l+1;
 98             tree tmp=query(1,l,r);
 99             ull t1=tmp.k+(ull)(L-1)*d;
100             t1=(t1+tmp.k)*L;
101             if (t1!=tmp.sum*2)
102             {
103                 puts("No");
104                 continue;
105             }
106             ull t2=(ull)L*((ull)6*(ull)(tmp.k-d)*(tmp.k+d*L)+(ull)d*d*(L+1)*(2*L+1));
107             if (t2!=tmp.psum*6)
108             {
109                 puts("No");
110                 continue;
111             }
112             puts("Yes");
113             cnt++;
114         }
115     }
116     return 0;
117 }
时间: 2025-01-09 16:37:33

BZOJ 4373的相关文章

AC日记——算术天才⑨与等差数列 bzoj 4373

4373 思路: 判断一个数列是否是等差数列: 1,最大值减去最小值==(区间个数-1)*k: 2,gcd==k: 3,不能有重复(不会这判断这一条,但是数据水就过了): 来,上代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 300005 struct TreeNodeType

bzoj 4373 算术天才⑨与等差数列

4373: 算术天才⑨与等差数列 Time Limit: 10 Sec  Memory Limit: 128 MBhttp://www.lydsy.com/JudgeOnline/problem.php?id=4373 Description 算术天才⑨非常喜欢和等差数列玩耍.有一天,他给了你一个长度为n的序列,其中第i个数为a[i].他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序后能否形成公差为k的等差数列.当然,他还会不断修改其中的某一项.为了不被他鄙视,你必须要

bzoj 4373: 算术天才⑨与等差数列 hash

题目链接 题目大意:  给你n个数, 给两种操作, 一种给你l, r, k,问你[l, r]区间里的数排序后能否构成一个公差为k的等差数列. 另一种是将位置x的数变为y. 强制在线. 可以用hash来做, 用线段树保存一个区间里的最小值, 和, 以及平方的和. 然后每次询问, 假设这个区间构成等差数列,那么首项为这个区间的最小值, 然后按公式算出以minn为首项, k为公差的数列的和, 为a1*len+len*(len-1)/2*d, 然后算出平方的和, 相当于sigma(i : 0 to le

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比

洛谷 P2709 BZOJ 3781 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3

BZOJ 1012: [JSOI2008]最大数maxnumber(线段树)

012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列

【BZOJ】【1016】【JSOI2008】最小生成树计数

Kruskal/并查集+枚举 唉我还是too naive,orz Hzwer 一开始我是想:最小生成树删掉一条边,再加上一条边仍是最小生成树,那么这两条边权值必须相等,但我也可以去掉两条权值为1和3的,再加上权值为2和2的,不也满足题意吗?事实上,如果这样的话……最小生成树应该是1和2,而不是1和3或2和2!!! 所以呢?所以对于一个图来说,最小生成树有几条边权为多少的边,都是固定的!所以我们可以做一遍Kruskal找出这些边权,以及每种边权出现的次数.然后,对于每种边权,比方说出现了$v_i$