1. 程式人生 > >[BZOJ4373]算術天才⑨與等差數列

[BZOJ4373]算術天才⑨與等差數列

題目 nbsp cpp style 長度 數列 在線 init node

題目大意:給你一個序列和一些操作,讓你實現這些操作,並回答詢問。具體操作見題目。

解題思路:因為輸入的東西需要xor之前輸出的yes個數,所以本題是強制在線。

一個序列形成等差數列必須滿足以下三個條件:

1.序列最小數+公差*(項數-1)=序列最大數;

2.該區間差分後的gcd=公差;

3.數字各不相等。

前兩個條件用線段樹就可以輕松維護,第三個條件貌似需要用一些神奇的方法。

然而這題可以維護平方和,2、3條件就可以忽略了。

不過平方和會很大,甚至超過long long,要進行取模,而且平方和公式裏有個除以6,還要用什麽逆元。

於是就有dalao用int,讓它自然溢出,在維護平方和時直接乘6,完美解決了上面的問題。orz orz orz

等差數列平方和公式(L,等差數列長度;d,公差)$a_1 ^2 L+a_1dL(L-1)+\frac{d^2 L(L-1)(2L-1)}{6}$

於是我用了此dalao的方法,此題就AC了。

C++ Code:

#include<cstdio>
#include<algorithm>
#include<cctype>
using namespace std;
char buf[10000020];
int bufpos;
inline void init(){
	buf[fread(buf,1,10000020,stdin)]=‘\0‘;
    bufpos=0;
}
inline int readint(){
	int p=0;
	for(;!isdigit(buf[bufpos]);bufpos++);
	for(;isdigit(buf[bufpos]);bufpos++)
	p=p*10+buf[bufpos]-‘0‘;
	return p;
}
struct Node{
	int sum,Min;
	Node():sum(0),Min(2000000000){}
	Node operator +(const Node& rhs)const{
		Node s;
		s.sum=sum+rhs.sum;
		s.Min=min(rhs.Min,Min);
		return s;
	}
}d[1100003];
int n,m,yes=0,x,y,l,r,k;
inline void update(int cur){
	d[cur].Min=min(d[cur<<1].Min,d[cur<<1|1].Min);
	d[cur].sum=d[cur<<1].sum+d[cur<<1|1].sum;
}
void make(int l,int r,int cur){
	if(l==r){
		d[cur].Min=readint();
		d[cur].sum=d[cur].Min*d[cur].Min*6;
		return;
	}
	int mid=l+r>>1;
	make(l,mid,cur<<1);
	make(mid+1,r,cur<<1|1);
	update(cur);
}
void change(int l,int r,int cur,int x,int y){
	if(l==r){
		d[cur].Min=y;
		d[cur].sum=y*y*6;
		return;
	}
	int mid=l+r>>1;
	if(x<=mid)change(l,mid,cur<<1,x,y);else
	change(mid+1,r,cur<<1|1,x,y);
	update(cur);
}
Node query(int l,int r,int cur,int L,int R){
	if(L<=l&&r<=R)return d[cur];
	int mid=l+r>>1;
	Node ans;
	if(L<=mid)ans=query(l,mid,cur<<1,L,R);
	if(mid<R)ans=ans+query(mid+1,r,cur<<1|1,L,R);
	return ans;
}
int main(){
	init();
	n=readint(),m=readint();
	make(1,n,1);
	for(;m--;){
		int op=readint();
		if(op==1){
			x=readint()^yes,y=readint()^yes;
			change(1,n,1,x,y);
		}else{
			l=readint()^yes,r=readint()^yes,k=readint()^yes;
			int len=r-l+1;
			Node p=query(1,n,1,l,r);
			if(p.sum==p.Min*p.Min*len*6+p.Min*k*len*(len-1)*6+k*k*len*(len-1)*(2*len-1)){
				puts("Yes");
				yes++;
			}else puts("No");
		}
	}
	return 0;
}

[BZOJ4373]算術天才⑨與等差數列