• [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 }
  • 相关阅读:
    GridView
    BaseAdapter
    ArrayAdapter,SimpleAdapter
    消息机制,Handler
    进度条对话框
    随机二选一
    (二十五)WebDriver API之上传文件
    (二十四)WebDriver API之警告框处理
    linux常用命令大全
    (二十三)WebDriver API之多窗口切换
  • 原文地址:https://www.cnblogs.com/skylee03/p/7182235.html
Copyright © 2020-2023  润新知