首页 > 代码库 > [BZOJ4373]算术天才⑨与等差数列

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

思路:

构造等差数列的条件:
1、区间内所有数差分的$gcd=x$
2、区间内$max-min=(r-l)*k$
3、区间内数字不相同
线段树维护最大值,最小值以及差分。
对于每次询问判断上述三种情况,如果满足则说明可以构成等差数列。

需要特判的情况:
1、$k=0$,此时条件3不需要满足
2、$l=r$,此时数列(单个数字)一定能构成等差数列
然而由于数据比较水,所以条件3不判断也没关系。
实测加上条件3判断8936ms,不判断2836ms。
另外有一种hash的做法。
Rank1在hash的基础上还用了zkw线段树,只跑了740ms。

  1 #include<set>  2 #include<map>  3 #include<cmath>  4 #include<cstdio>  5 #include<cctype>  6 #include<utility>  7 #include<algorithm>  8 inline int getint() {  9     char ch; 10     while(!isdigit(ch=getchar())); 11     int x=ch^0; 12     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^0); 13     return x; 14 } 15 const int N=300001,inf=0x7fffffff; 16 int a[N]={0}; 17 class SegmentTreeM { 18     #define _left <<1 19     #define _right <<1|1 20     private: 21         int max[N<<2],min[N<<2]; 22         void push_up(const int p) { 23             max[p]=std::max(max[p _left],max[p _right]); 24             min[p]=std::min(min[p _left],min[p _right]); 25         } 26     public: 27         void build(const int p,const int b,const int e) { 28             if(b==e) { 29                 max[p]=min[p]=a[b]; 30                 return; 31             } 32             int mid=(b+e)>>1; 33             build(p _left,b,mid); 34             build(p _right,mid+1,e); 35             push_up(p); 36         } 37         void modify(const int p,const int b,const int e,const int x) { 38             if(b==e) { 39                 max[p]=min[p]=a[x]; 40                 return; 41             } 42             int mid=(b+e)>>1; 43             if(x<=mid) modify(p _left,b,mid,x); 44             if(x>mid) modify(p _right,mid+1,e,x); 45             push_up(p); 46         } 47         std::pair<int,int> query(const int p,const int b,const int e,const int l,const int r) { 48             if((l==b)&&(e==r)) return std::make_pair(max[p],min[p]); 49             int mid=(b+e)>>1; 50             std::pair<int,int> ans=std::make_pair(0,inf); 51             if(l<=mid) { 52                 std::pair<int,int> s=query(p _left,b,mid,l,std::min(mid,r)); 53                 ans=std::make_pair(std::max(ans.first,s.first),std::min(ans.second,s.second)); 54             } 55             if(r>mid) { 56                 std::pair<int,int> s=query(p _right,mid+1,e,std::max(mid+1,l),r); 57                 ans=std::make_pair(std::max(ans.first,s.first),std::min(ans.second,s.second)); 58             } 59             return ans; 60         } 61         bool check(const int n,const int l,const int r,const int k) { 62             std::pair<int,int> t=query(1,1,n,l,r); 63             return t.first-t.second==(r-l)*k; 64         } 65 }; 66 SegmentTreeM m_t; 67 int d[N]={0}; 68 class SegmentTreeGCD { 69     #define _left <<1 70     #define _right <<1|1 71     private: 72         int val[N<<2]; 73         int gcd(const int x,const int y) { 74             if(!x&&!y) return 0; 75             return y?gcd(y,x%y):x; 76         } 77         void push_up(const int p) { 78             val[p]=gcd(val[p _left],val[p _right]); 79         } 80     public: 81         void build(const int p,const int b,const int e) { 82             if(b==e) { 83                 val[p]=d[b]; 84                 return; 85             } 86             int mid=(b+e)>>1; 87             build(p _left,b,mid); 88             build(p _right,mid+1,e); 89             push_up(p); 90         } 91         void modify(const int p,const int b,const int e,const int x) { 92             if(b==e) { 93                 val[p]=d[x]; 94                 return; 95             } 96             int mid=(b+e)>>1; 97             if(x<=mid) modify(p _left,b,mid,x); 98             if(x>mid) modify(p _right,mid+1,e,x); 99             push_up(p);100         }101         void modify(const int p,const int b,const int e,const int x,const int y) {102             int mid=(b+e)>>1;103             if(y<=mid) modify(p _left,b,mid,x,y);104             if(x>mid) modify(p _right,mid+1,e,x,y);105             if((x==mid)&&(y==mid+1)) modify(p _left,b,mid,x),modify(p _right,mid+1,e,y);106             push_up(p);107         }108         int query(const int p,const int b,const int e,const int l,const int r) {109             if((l==b)&&(e==r)) return val[p];110             int ans=0;111             int mid=(b+e)>>1;112             if(l<=mid) ans=gcd(ans,query(p _left,b,mid,l,std::min(mid,r)));113             if(r>mid) ans=gcd(ans,query(p _right,mid+1,e,std::max(mid+1,l),r));114             return ans;115         }116         bool check(const int n,const int l,const int r,const int k) {117             return query(1,1,n-1,l,r-1)==k;118         }119 };120 SegmentTreeGCD gcd_t;121 /*class Sets {122     private:123         std::map<int,std::set<int> > pre;124     public:125         void erase(const int x) {126             pre[a[x]].erase(x);127         }128         void insert(const int x) {129             pre[a[x]].insert(x);130         }131         bool check(const int l,const int r) {132             for(int i=l;i<=r;i++) {133                 std::set<int>::iterator p=pre[a[i]].find(i);134                 if(p==pre[a[i]].end()||p==pre[a[i]].begin()) continue;135                 if(*--p>=l) return false;136             }137             return true;138         }139 };140 Sets s;*/141 inline bool check(const int n,const int l,const int r,const int k) {142     if(l==r) return true;143     if(!k) return m_t.check(n,l,r,k)&&gcd_t.check(n,l,r,k);144     return m_t.check(n,l,r,k)&&gcd_t.check(n,l,r,k)/*&&s.check(l,r)*/;145 }146 int main() {147     int n=getint(),m=getint();148     for(int i=1;i<=n;i++) {149         a[i]=getint();150         if(i>1) d[i-1]=abs(a[i]-a[i-1]);151         //s.insert(i);152     }153     m_t.build(1,1,n);154     gcd_t.build(1,1,n-1);155     int count=0;156     while(m--) {157         int op=getint();158         if(op==1) {159             int x=getint()^count;160             //s.erase(x);161             a[x]=getint()^count;162             //s.insert(x);163             m_t.modify(1,1,n,x);164             if(x!=n) d[x]=abs(a[x+1]-a[x]);165             if(x>1) d[x-1]=abs(a[x]-a[x-1]);166             if(x==n) gcd_t.modify(1,1,n-1,x-1);167             if(x<=1) gcd_t.modify(1,1,n-1,x);168             if((x>1)&&(x!=n)) gcd_t.modify(1,1,n-1,x-1,x);169         }170         if(op==2) {171             int l=getint()^count,r=getint()^count,k=getint()^count;172             if(check(n,l,r,k)) {173                 puts("Yes");174                 count++;175             }176             else {177                 puts("No");178             }179         }180     }181     return 0;182 }

 

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