bzoj 4373: 算术天才⑨与等差数列
2016-04-20 15:52
423 查看
看到这个限制条件非常强,就不难考虑到hash。
存在一个性质,只要知道这个区间的最大值,最小值,希望得到的等差序列就唯一确定,需要干的工作仅仅是看原来的序列和这个序列是否相同。
首先,用各种特判:
k=0很好做,若k!=0
1.相邻两项的差的gcd是k的倍数->维护差的gcd
2.没有相同的项->维护pre的最大值
3.区间和等于这个等差序列的和->维护区间sum
用线段树维护一下就可以。
另一种做法,查询等差序列的和,等差序列各项的平方的和,看是否相等。
我用的是第二种。
存在一个性质,只要知道这个区间的最大值,最小值,希望得到的等差序列就唯一确定,需要干的工作仅仅是看原来的序列和这个序列是否相同。
首先,用各种特判:
k=0很好做,若k!=0
1.相邻两项的差的gcd是k的倍数->维护差的gcd
2.没有相同的项->维护pre的最大值
3.区间和等于这个等差序列的和->维护区间sum
用线段树维护一下就可以。
另一种做法,查询等差序列的和,等差序列各项的平方的和,看是否相等。
我用的是第二种。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md 100000007
#define N 300010
using namespace std;
struct Tr { ll s1,s2,mn,mx;} tr[4*N];
ll a[N],s[N];
Tr update(Tr a,Tr b) { return (Tr){a.s1+b.s1,(a.s2+b.s2)%md,min(a.mn,b.mn),max(a.mx,b.mx)};}
void build(int i,int l,int r)
{
if (l==r) { tr[i]=(Tr){a[l],a[l]*a[l]%md,a[l],a[l]}; return;}
int mid=(l+r)>>1;
build(i<<1,l,mid); build(i<<1|1,mid+1,r);
tr[i]=update(tr[i<<1],tr[i<<1|1]);
}
void modify(int i,int l,int r,int x)
{
if (l==r) { tr[i]=(Tr){a[l],a[l]*a[l]%md,a[l],a[l]}; return;}
int mid=(l+r)>>1;
if (x<=mid) modify(i<<1,l,mid,x);
else modify(i<<1|1,mid+1,r,x);
tr[i]=update(tr[i<<1],tr[i<<1|1]);
}
Tr query(int i,int l,int r,int ql,int qr)
{
if (ql<=l&&r<=qr) return tr[i];
int mid=(l+r)>>1;
if (qr<=mid) return query(i<<1,l,mid,ql,qr);
if (mid+1<=ql) return query(i<<1|1,mid+1,r,ql,qr);
return update(query(i<<1,l,mid,ql,qr),query(i<<1|1,mid+1,r,ql,qr));
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
s[0]=0; for (ll i=1;i<n;i++) s[i]=(s[i-1]+i*i)%md;
build(1,1,n);
int Y=0;
for (int i=1;i<=m;i++)
{
int ty;
scanf("%d",&ty);
if (ty==1)
{
int x,y;
scanf("%d%d",&x,&y); x^=Y; y^=Y; a[x]=y;
modify(1,1,n,x);
}
else
{
ll l,r,k;
scanf("%lld%lld%lld",&l,&r,&k);
l^=Y; r^=Y; k^=Y;
if (l==r) { Y++; printf("Yes\n"); }
else
{
Tr ans=query(1,1,n,l,r); ll sz=r-l+1;
if (ans.mx!=ans.mn+k*(sz-1)) { printf("No\n"); continue;}
ll s1=(ans.mx+ans.mn)*sz/2,s2=(ans.mn*ans.mn%md*sz+ans.mn*k%md*sz%md*(sz-1)+k*k%md*s[sz-1])%md;
if (s1==ans.s1&&s2==ans.s2) { Y++; printf("Yes\n"); } else printf("No\n");
}
}
}
return 0;
}
相关文章推荐
- JavaScript表单填写时,数据索引筛选自动填写功能效果
- MongoDB设置环境变量与设置成Windows服务
- 常见通信协议HTTP、TCP、UDP的简单介绍
- 常见通信协议HTTP、TCP、UDP的简单介绍
- TestNG 学习总结 - 测试过程(五)
- HashTable 和 HashSet 的源码分析
- GCD 第三篇 dispatch_group
- linux下添加PATH环境变量
- 从此不求人:自主研发一套PHP前端开发框架(26)
- 依赖注入框架Autofac的简单使用
- 机器学习/数据挖掘/十大经典算法总结
- js中namespace命名空间模式
- SQLMAP常用选项
- 桌面widget详解(四)——桌面音乐播放器(实战)
- 【转】WEB应用中的SESSION知多少?
- Could not access the Package Manager. Is the system running
- error C2079: “pcl::KdTreeFLANN<PointT>::param_radius_”使用未定义的 struct“flann::SearchParams”
- ETW-Event Tracing for Windows入门
- 用 cmake 构建Qt工程(对比qmake进行学习)
- unity3d调用windows窗体