[bzoj4373]算术天才⑨与等差数列

用一种类似于hash的做法(就是比较假可能会被卡的做法),维护区间最小值、最大值和区间和,根据这些信息来判断是否矛盾即可
当然还有比较严谨的方法,维护区间min、区间max、区间相邻两数的gcd和区间pre的max,这样就可以保证答案的正确性

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 300005
 4 #define L (k<<1)
 5 #define R (L+1)
 6 #define mid (l+r>>1)
 7 #define ll long long
 8 struct ji{
 9     int mi,ma;
10     ll sum;
11 }o,k,f[N<<3];
12 int n,m,p,x,y,z,ans;
13 ji up(ji x,ji y){
14     ji z;
15     z.mi=min(x.mi,y.mi);
16     z.ma=max(x.ma,y.ma);
17     z.sum=x.sum+y.sum;
18     return z;
19 }
20 void update(int k,int l,int r,int x,int y){
21     if (l==r){
22         f[k].mi=f[k].ma=f[k].sum=y;
23         return;
24     }
25     if (x<=mid)update(L,l,mid,x,y);
26     else update(R,mid+1,r,x,y);
27     f[k]=up(f[L],f[R]);
28 }
29 ji query(int k,int l,int r,int x,int y){
30     if ((l>y)||(x>r))return o;
31     if ((x<=l)&&(r<=y))return f[k];
32     return up(query(L,l,mid,x,y),query(R,mid+1,r,x,y));
33 }
34 int main(){
35     scanf("%d%d",&n,&m);
36     o.mi=0x3f3f3f3f;
37     for(int i=1;i<=n;i++){
38         scanf("%d",&x);
39         update(1,1,n,i,x);
40     }
41     for(int i=1;i<=m;i++){
42         scanf("%d%d%d",&p,&x,&y);
43         x^=ans;
44         y^=ans;
45         if (p==1)update(1,1,n,x,y);
46         else{
47             scanf("%d",&z);
48             z^=ans;
49             k=query(1,1,n,x,y);
50             bool flag=0;
51             if (1LL*z*(y-x)!=k.ma-k.mi)flag=1;
52             if ((k.mi+k.ma)*(y-x+1LL)/2!=k.sum)flag=1;
53             if (flag)printf("No\n");
54             else{
55                 printf("Yes\n");
56                 ans++;
57             }
58         }
59     }
60 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/11835470.html