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

题解:  很显然这个题 等差数列没有办法维护  那么我们考虑一段区间为等差数列 那么应该满足

1.最大值和最小值的差等于(r-l)*k

2.任意相邻差值的绝对值的gcd与k的gcd等于k

3.特判k==0的情况

3.用set去重

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const double eps=1e-8;
const int inf=1e9+7;
#define ll long long
using namespace std;
// struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
// void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
	ll x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
	return x*f;
}

int Gcd[MAXN<<2],pre[MAXN<<2],minn[MAXN<<2],maxx[MAXN<<2],vis[MAXN],a[MAXN],b[MAXN];
int cnt,tot;
map<int,int>ma;
map<int,int>::iterator ite;
set<int>s[MAXN<<1];
set<int>::iterator ip,id;
void up(int x){
	Gcd[x]=__gcd(Gcd[x<<1],Gcd[x<<1|1]);
	pre[x]=max(pre[x<<1],pre[x<<1|1]);
	minn[x]=min(minn[x<<1],minn[x<<1|1]);
	maxx[x]=max(maxx[x<<1],maxx[x<<1|1]);
}
void built(int rt,int l,int r){
	if(l==r){Gcd[rt]=b[l];minn[rt]=maxx[rt]=a[l];pre[rt]=vis[l];return ;}
	int mid=(l+r)>>1;
	built(rt<<1,l,mid);
	built(rt<<1|1,mid+1,r);
	up(rt);
}
void update1(int rt,int l,int r,int t,int vul){
	if(l==r){pre[rt]=vul;return ;}
	int mid=(l+r)>>1;
	if(t<=mid)update1(rt<<1,l,mid,t,vul);
	else update1(rt<<1|1,mid+1,r,t,vul);
	pre[rt]=max(pre[rt<<1],pre[rt<<1|1]);
}
void update2(int rt,int l,int r,int t,int vul){
	if(l==r){Gcd[rt]=abs(vul-a[l-1]);minn[rt]=maxx[rt]=vul;return ;}
	int mid=(l+r)>>1;
	if(t<=mid)update2(rt<<1,l,mid,t,vul);
	else update2(rt<<1|1,mid+1,r,t,vul);
	up(rt);
}
void update3(int rt,int l,int r,int t,int vul){
	if(l==r){Gcd[rt]=abs(vul-a[l]);return ;}
	int mid=(l+r)>>1;
	if(t<=mid)update3(rt<<1,l,mid,t,vul);
	else update3(rt<<1|1,mid+1,r,t,vul);
	up(rt);
}
int ans;
void querty1(int rt,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr){ans=__gcd(ans,Gcd[rt]);return ;}
	int mid=(l+r)>>1;
	if(ql<=mid)querty1(rt<<1,l,mid,ql,qr);
	if(qr>mid)querty1(rt<<1|1,mid+1,r,ql,qr);
}
int ans1,ans2,ans3;
void querty2(int rt,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr){ans1=min(ans1,minn[rt]);ans2=max(ans2,maxx[rt]);ans3=max(ans3,pre[rt]);return ;}
	int mid=(l+r)>>1;
	if(ql<=mid)querty2(rt<<1,l,mid,ql,qr);
	if(qr>mid)querty2(rt<<1|1,mid+1,r,ql,qr);
}
int main(){
	int n,m;n=read();m=read();cnt=tot=0;
	inc(i,1,n){
		a[i]=read();
		if(ma.find(a[i])==ma.end())ma[a[i]]=++cnt,s[cnt].insert(i),vis[i]=0;
		else{
			ite=ma.find(a[i]);
			ip=s[ite->second].lower_bound(i);ip--;vis[i]=(*ip);s[ite->second].insert(i);
		}
		b[i]=abs(a[i]-a[i-1]);
		//cout<<b[i]<<" ";
	}
	//cout<<endl;
	built(1,1,n);int op,l,r,k;
	inc(i,1,m){
		op=read();l=read();r=read();l^=tot;r^=tot;
		if(op==1){
			update2(1,1,n,l,r);
			if(l!=n)update3(1,1,n,l+1,r);
			ite=ma.find(a[l]);ip=s[ite->second].lower_bound(l+1);id=s[ite->second].lower_bound(l);
			if(ip!=s[ite->second].end()){
				if(id==s[ite->second].begin())update1(1,1,n,(*ip),0),s[ite->second].erase(id);
				else {
					int t=(*ip);ip=id;id--;
					update1(1,1,n,t,(*id));s[ite->second].erase(ip);
				}
			}
			ite=ma.find(r);
			if(ite==ma.end())ma[r]=++cnt,s[cnt].insert(l),update1(1,1,n,l,0);
			else{
				ip=s[ite->second].lower_bound(l);
				if(ip!=s[ite->second].end()){update1(1,1,n,(*ip),l);}				
				if(ip==s[ite->second].begin()){update1(1,1,n,l,0);}
				else ip--,update1(1,1,n,l,(*ip));
				s[ite->second].insert(l);
			}
			a[l]=r;
		}
		else{
			//cout<<i<<"::::"<<op<<" "<<l<<" "<<r<<endl;
			k=read();k^=tot;
			if(l==r){tot++;puts("Yes");continue;}
			//k^=tot;
			ans=0;querty1(1,1,n,l+1,r);
			ans1=inf;ans2=ans3=0;querty2(1,1,n,l,r);
			//cout<<i<<" "<<k<<"===="<<ans1<<" "<<ans2<<" "<<ans<<endl;
			if(k==0&&ans1==ans2){tot++;puts("Yes");continue;}
			else if(k==0&&ans1!=ans2){puts("No");continue;}
			if(__gcd(ans,k)!=k){puts("No");continue;}
			int t=(ans2-ans1)%k;int t1=(ans2-ans1)/k;
			//cout<<t<<" "<<t1<<" "<<i<<endl;
			if(ans3<l&&t==0&&t1==r-l){tot++;puts("Yes");continue;}
			else puts("No");
		}
	}
	return 0;
}

  

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

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

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

 

posted @ 2018-09-10 19:39  wang9897  阅读(149)  评论(0编辑  收藏  举报