BZOJ 4373: 算术天才⑨与等差数列 线段树

Code:

#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\n"),++cc;             
            else if(k==0) {                       
                if(A::qmin(1,n,1,l,r)==A::qmax(1,n,1,l,r)) printf("Yes\n"),++cc;    
                else printf("No\n");   
            }
            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\n"), ++cc;        
                        }
                    } 
                }
                else flag=1;  
                if(flag) printf("No\n");     
            }
        }
    }     
    return 0; 
}     

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值