zoukankan      html  css  js  c++  java
  • BZOJ 4373: 算术天才⑨与等差数列 线段树

    Description

    算术天才⑨非常喜欢和等差数列玩耍。
    有一天,他给了你一个长度为n的序列,其中第i个数为a[i]。
    他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序后能否形成公差为k的等差数列。
    当然,他还会不断修改其中的某一项。
    为了不被他鄙视,你必须要快速并正确地回答完所有问题。
    注意:只有一个数的数列也是等差数列。

    Input

    第一行包含两个正整数n,m(1<=n,m<=300000),分别表示序列的长度和操作的次数。
    第二行包含n个整数,依次表示序列中的每个数a[i](0<=a[i]<=10^9)。
    接下来m行,每行一开始为一个数op,
    若op=1,则接下来两个整数x,y(1<=x<=n,0<=y<=10^9),表示把a[x]修改为y。
    若op=2,则接下来三个整数l,r,k(1<=l<=r<=n,0<=k<=10^9),表示一个询问。
    在本题中,x,y,l,r,k都是经过加密的,都需要异或你之前输出的Yes的个数来进行解密。

    Output

    输出若干行,对于每个询问,如果可以形成等差数列,那么输出Yes,否则输出No。

    题解:

    公差 $k$ 和区间长度都是固定的,所以等差数列也是唯一确定的.
    这里分几个情况:
    $l=r$,无限制条件.
    $k=0$,所有数必须都相同.
    其他情况,令区间最大值为 $Max$,最小值为 $Min$,那么 $Max-Min=(len-1) imes k$
    除此之外,还需满足没有数字重复出现,任意两个数的差都是 $k$ 的倍数 
    #include <cstdio>
    #include <string>
    #include <cstring>   
    #include <algorithm>   
    #include <map>
    #include <set>      
    #define ll long long 
    using namespace std;  
    namespace IO { 
        #define rint register int 
        void setIO(string s) {
            string in=s+".in",out=s+".out"; 
            freopen(in.c_str(),"r",stdin);   
            freopen(out.c_str(),"w",stdout);           
        }          
        inline int read(){
            rint x=0,f=1;char ch=getchar();
            while (ch<'0' || ch>'9'){if (ch=='-')f=-1;ch=getchar();}
            while ('0'<=ch && ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
            return x*f;
        }
    };   
    const int maxn=300006;  
    const int inf=1000000002; 
    int n,m; 
    int arr[maxn],brr[maxn];     
    int GCD(int a,int b) {
        return b?GCD(b,a%b):a;       
    }
    namespace A { 
        int minv[maxn<<2],maxv[maxn<<2];     
        void pushup(int l,int r,int now) {     
            int mid=(l+r)>>1;   
            minv[now]=minv[now<<1]; 
            maxv[now]=maxv[now<<1];            
            if(r>mid) {
                minv[now]=min(minv[now],minv[now<<1|1]);    
                maxv[now]=max(maxv[now],maxv[now<<1|1]);   
            }
        }
        void build(int l,int r,int now) {    
            if(l==r) {        
                minv[now]=maxv[now]=arr[l];  
                return;   
            } 
            int mid=(l+r)>>1;   
            build(l,mid,now<<1);  
            if(r>mid) build(mid+1,r,now<<1|1); 
            pushup(l,r,now);  
        } 
        void update(int l,int r,int now,int p,int v) {
            if(l==r) {
                minv[now]=maxv[now]=v;    
                return;  
            } 
            int mid=(l+r)>>1;  
            if(p<=mid) update(l,mid,now<<1,p,v);  
            else update(mid+1,r,now<<1|1,p,v);  
            pushup(l,r,now);    
        }
        int qmax(int l,int r,int now,int L,int R) {
            if(l>=L&&r<=R) return maxv[now];   
            int mid=(l+r)>>1,re=0; 
            if(mid>=L) re=max(re,qmax(l,mid,now<<1,L,R));  
            if(R>mid) re=max(re,qmax(mid+1,r,now<<1|1,L,R)); 
            return re; 
        } 
        int qmin(int l,int r,int now,int L,int R) {
            if(l>=L&&r<=R) return minv[now];  
            int mid=(l+r)>>1,re=inf;   
            if(mid>=L) re=min(re,qmin(l,mid,now<<1,L,R)); 
            if(R>mid) re=min(re,qmin(mid+1,r,now<<1|1,L,R)); 
            return re;    
        }
    }; 
    namespace lst { 
        int id;  
        int lst[maxn<<2];  
        map<int,int>idx;    
        set<int>S[maxn<<1];  
        set<int>::iterator it;  
        void insert(int v,int i) { 
            if(!idx[v]) idx[v]=++id;   
            int cur=idx[v];
            S[cur].insert(i);    
        }    
        void pushup(int l,int r,int now) {   
            int mid=(l+r)>>1; 
            lst[now]=lst[now<<1];  
            if(r>mid) lst[now]=max(lst[now],lst[now<<1|1]);             
        }
        void build(int l,int r,int now) {
            if(l==r) {  
                int cur=idx[arr[l]];     
                it=S[cur].lower_bound(l);         
                if(it==S[cur].begin()) lst[now]=-inf;   
                else {
                    it--;    
                    lst[now]=(*it);   
                }  
                return; 
            }
            int mid=(l+r)>>1;   
            if(l<=mid) build(l,mid,now<<1);    
            if(r>mid) build(mid+1,r,now<<1|1);   
            pushup(l,r,now);      
        }   
        void update(int l,int r,int now,int p) {       
            if(l==r) {    
                int cur=idx[arr[l]];   
                it=S[cur].lower_bound(l);     
                if(it==S[cur].begin()) lst[now]=-inf; 
                else {    
                    it--; 
                    lst[now]=(*it);  
                } 
                return; 
            } 
            int mid=(l+r)>>1;  
            if(p<=mid) update(l,mid,now<<1,p); 
            else update(mid+1,r,now<<1|1,p);   
            pushup(l,r,now);    
        }
        int query(int l,int r,int now,int L,int R) {
            if(l>=L&&r<=R) return lst[now];   
            int mid=(l+r)>>1,re=0; 
            if(L<=mid) re=max(re, query(l,mid,now<<1,L,R));  
            if(R>mid) re=max(re, query(mid+1,r,now<<1|1,L,R));     
            return re;    
        }
        void modify(int v,int i) {
            if(!idx[v]) idx[v]=++id;  
            int cur=idx[v];                   
            S[idx[arr[i]]].erase(i);     
            it=S[idx[arr[i]]].lower_bound(i+1);      
            if(it!=S[idx[arr[i]]].end()) {  
                update(1,n,1,(*it));    
            }
            S[cur].insert(i), arr[i]=v;         
            update(1,n,1,i);    
        }   
    };   
    namespace delta { 
        int gc[maxn<<2];    
        void pushup(int l,int r,int now) {
            int mid=(l+r)>>1; 
            gc[now]=gc[now<<1];   
            if(r>mid) gc[now]=GCD(gc[now<<1|1],gc[now]);    
        }
        void build(int l,int r,int now) { 
            if(l==r) {   
                gc[now]=brr[l];   
                return; 
            }
            int mid=(l+r)>>1;            
            if(l<=mid) build(l,mid,now<<1);  
            if(r>mid) build(mid+1,r,now<<1|1);     
            pushup(l,r,now); 
        }     
        void update(int l,int r,int now,int p,int v) {
            if(l==r) {
                gc[now]=v;          
                return; 
            }
            int mid=(l+r)>>1;  
            if(p<=mid) update(l,mid,now<<1,p,v);   
            else update(mid+1,r,now<<1|1,p,v); 
            pushup(l,r,now);    
        }   
        int query(int l,int r,int now,int L,int R) {
            if(l>=L&&r<=R) return gc[now];   
            int mid=(l+r)>>1,re=0;      
            if(L<=mid) re=query(l,mid,now<<1,L,R);    
            if(R>mid) re=re?GCD(re,query(mid+1,r,now<<1|1,L,R)):query(mid+1,r,now<<1|1,L,R);     
            return re;      
        }
    };    
    int main() {
        using namespace IO; 
        // IO::setIO("input");    
        int i,j; 
        n=read(),m=read();   
        for(i=1;i<=n;++i) {     
            arr[i]=read();  
            lst::insert(arr[i],i);              
        }
        for(i=1;i<=n;++i) brr[i]=abs(arr[i+1]-arr[i]);      
        A::build(1,n,1); 
        delta::build(1,n-1,1);
        lst::build(1,n,1);     
        int cc=0; 
        int h=0; 
        for(int cas=1;cas<=m;++cas) {
            int op=read();   
            if(op==1) {
                int x,y;  
                x=read(),y=read(),x^=cc,y^=cc;              
                if(arr[x]==y) continue;       
                lst::modify(y,x);             
                A::update(1,n,1,x,y);           
                if(x==1) delta::update(1,n-1,1,1,abs(arr[2]-arr[1]));         
                else if(x==n) delta::update(1,n-1,1,n-1,abs(arr[n]-arr[n-1]));           
                else { 
                    delta::update(1,n-1,1,x-1,abs(arr[x]-arr[x-1])); 
                    delta::update(1,n-1,1,x,abs(arr[x+1]-arr[x]));                
                }
            } 
            if(op==2) {     
                int l,r,k;  
                l=read(),r=read(),k=read();    
                l^=cc,r^=cc,k^=cc;               
                if(l==r) printf("Yes
    "),++cc;             
                else if(k==0) {                       
                    if(A::qmin(1,n,1,l,r)==A::qmax(1,n,1,l,r)) printf("Yes
    "),++cc;    
                    else printf("No
    ");   
                }
                else {           
                    int len=r-l;     
                    int minn=A::qmin(1,n,1,l,r), maxx=A::qmax(1,n,1,l,r);                       
                    int flag=0; 
                    if(maxx-minn==1ll*k*len) {                   
                        if(lst::query(1,n,1,l,r)>=l) flag=1;                                          
                        else {         
                            if(delta::query(1,n-1,1,l,r-1)%k) flag=1;  
                            else {
                                printf("Yes
    "), ++cc;        
                            }
                        } 
                    }
                    else flag=1;  
                    if(flag) printf("No
    ");     
                }
            }
        }     
        return 0; 
    }     
    

      

  • 相关阅读:
    阻止事件的默认行为,例如click <a>后的跳转~
    阻止事件冒泡
    IE67不兼容display:inline-block,CSS hack解决
    IE678不兼容CSS3 user-select:none(不可复制功能),需要JS解决
    JS数组常用方法总结
    json 只能用 for-in 遍历
    用实例的方式去理解storm的并发度
    OpenLDAP 搭建入门
    kafka api的基本使用
    kafka基本介绍
  • 原文地址:https://www.cnblogs.com/guangheli/p/11282512.html
Copyright © 2011-2022 走看看