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

题解
实际上
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+(n−1)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+(n−1)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+(n−1)k)1=na+(1+...(n−1))k=na+2n(n−1)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+(n−1)k)2=na2+2(1+2+...+n−1)ak+(12+22+...+(n−1)2)k2=na2+2n(n−1)ak+6n(n−1)(2n−1)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;
}

浙公网安备 33010602011771号