[海军国际项目办公室]等级

等级

题目大意

在这里插入图片描述

题解

实际上 n 2 n^2 n2暴力就可以过

由于题目要求某一区间是不是等级为 k k k的等差数列,我们可以考虑将其放在树上去判断。

对于一个等差数列,如果我们知道了它的首项与长度和公差,那么我们必定能将其表示出来。

设其首项为 a a a,长度为 n n n,公差为 d d d,则该序列为 { a , a + k , a + 2 k , . . . , a + ( n − 1 ) k } \{a,a+k,a+2k,...,a+(n-1)k\} {a,a+k,a+2k,...,a+(n1)k}

我们可以利用线段树得知该区间的最小值,就可以知道该区间应有的等差数列。我们只需要比较改区间实际构成不降序列是否与之一致即可。

如何比较两个序列是否一致呢,明显直接比较是会 T T T的,于是我们只好求出与hash了。

其实hash的方法很多,这里给出其中的一种。

我们可以对于一个区间算出它的 0 0 0次方和, 1 1 1次方和与 2 2 2次方和,再算出应有的等差数列的 0 0 0次方和, 1 1 1次方和, 2 2 2次方和,比较两者是否一致。
a 0 + ( a + k ) 0 + ( a + 2 k ) 0 + . . . + ( a + ( n − 1 ) k ) 0 = n a^0+(a+k)^0+(a+2k)^0+...+(a+(n-1)k)^0=n a0+(a+k)0+(a+2k)0+...+(a+(n1)k)0=n

a 1 + ( a + k ) 1 + ( a + 2 k ) 1 + . . . + ( a + ( n − 1 ) k ) 1 = n a + ( 1 + . . . ( n − 1 ) ) k = n a + n ( n − 1 ) 2 k a^1+(a+k)^1+(a+2k)^1+...+(a+(n-1)k)^1=na+(1+...(n-1))k=na+\frac{n(n-1)}{2}k a1+(a+k)1+(a+2k)1+...+(a+(n1)k)1=na+(1+...(n1))k=na+2n(n1)k

a 2 + ( a + k ) 2 + ( a + 2 k ) 2 + . . . + ( a + ( n − 1 ) k ) 2 = n a 2 + 2 ( 1 + 2 + . . . + n − 1 ) a k + ( 1 2 + 2 2 + . . . + ( n − 1 ) 2 ) k 2 = n a 2 + n ( n − 1 ) 2 a k + n ( n − 1 ) ( 2 n − 1 ) 6 k 2 a^2+(a+k)^2+(a+2k)^2+...+(a+(n-1)k)^2=na^2+2(1+2+...+n-1)ak+(1^2+2^2+...+(n-1)^2)k^2=na^2+\frac{n(n-1)}{2}ak+\frac{n(n-1)(2n-1)}{6}k^2 a2+(a+k)2+(a+2k)2+...+(a+(n1)k)2=na2+2(1+2+...+n1)ak+(12+22+...+(n1)2)k2=na2+2n(n1)ak+6n(n1)(2n1)k2

很明显 0 0 0次方, 1 1 1次方, 2 2 2次方都可以很容易地算出。

如果你实在信不过的话可以再加上 3 3 3次方, 4 4 4次方…

时间复杂度 O ( n l o g   n ) O\left(nlog\,n\right) O(nlogn)

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 300005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int orG=3,invG=332748118;
const int lim=300000;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
int qkpow(int a,int s){int t=1;while(s){if(s&1)t=1ll*a*t%mo;a=1ll*a*a%mo;s>>=1;}return t;}
int n,m,tot;LL a[MAXN];
struct ming{
	int minn,maxx;LL sum1,sum2;ming(){minn=INF;maxx=0;sum1=sum2=0;}
	ming(int X,int Y,LL Z,LL W){minn=X;maxx=Y;sum1=Z;sum2=W;}
};
class SegmentTree{
	public:
		ming tr[MAXN<<2];
		ming merge(ming x,ming y){
			ming res;
			res.minn=min(x.minn,y.minn);
			res.maxx=max(x.maxx,y.maxx);
			res.sum1=x.sum1+y.sum1; 
			res.sum2=x.sum2+y.sum2;
			return res;
		} 
		void pushup(int rt){tr[rt]=merge(tr[rt<<1],tr[rt<<1|1]);}
		void build(int rt,int l,int r){
			if(l==r){tr[rt]=ming(a[l],a[l],a[l],a[l]*a[l]);return ;}
			int mid=l+r>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);pushup(rt);
		}
		void modify(int rt,int l,int r,int ai,LL aw){
			if(l>r||l>ai||r<ai)return ;int mid=l+r>>1;
			if(l==r){tr[rt]=ming(aw,aw,aw,aw*aw);;return ;}
			if(ai<=mid)modify(rt<<1,l,mid,ai,aw);
			if(ai>mid)modify(rt<<1|1,mid+1,r,ai,aw);
			pushup(rt);
		}
		ming query(int rt,int l,int r,int al,int ar){
			ming res;if(l>r||l>ar||r<al||al>ar)return res;
			if(al<=l&&r<=ar)return tr[rt];int mid=l+r>>1;
			if(al<=mid)res=merge(res,query(rt<<1,l,mid,al,ar));
			if(ar>mid)res=merge(res,query(rt<<1|1,mid+1,r,al,ar));
			return res;
		}
}T;
signed main(){
	freopen("grade.in","r",stdin);
	freopen("grade.out","w",stdout); 
	read(n);read(m);
	for(int i=1;i<=n;i++)read(a[i]);
	T.build(1,1,n);
	for(int i=1;i<=m;i++){
		int typ,l,r,x,y;LL k;read(typ);
		if(typ==1){read(x);read(y);x^=tot;y^=tot;T.modify(1,1,n,x,y);}
		else{
			read(l);read(r);read(k);l^=tot;r^=tot;
			ming tmp=T.query(1,1,n,l,r);int len=r-l;
			if(tmp.maxx-tmp.minn!=1ll*len*k){puts("No");continue;}
			LL sum1=1ll*len*(len+1)/2LL,sum2=1ll*len*(len+1)*(2*len+1)/6LL;
			LL numm=1ll*(len+1)*tmp.minn+1ll*sum1*k;
			if(numm!=tmp.sum1){puts("No");continue;}
			LL summ=1ll*(len+1)*tmp.minn*tmp.minn+2ll*sum1*tmp.minn*k+1ll*sum2*k*k;
			if(summ!=tmp.sum2){puts("No");continue;}
			puts("Yes");tot++;
		}
	}
	return 0; 
} 

谢谢!!!

posted @ 2021-07-19 20:41  StaroForgin  阅读(10)  评论(0)    收藏  举报  来源