您的位置:首页 > 其它

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

2016-04-20 15:52 423 查看
看到这个限制条件非常强,就不难考虑到hash。
存在一个性质,只要知道这个区间的最大值,最小值,希望得到的等差序列就唯一确定,需要干的工作仅仅是看原来的序列和这个序列是否相同。
首先,用各种特判:
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: