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; 
    }     
    

      

  • 相关阅读:
    解决ListView异步加载数据之后不能点击的问题
    android点击实现图片放大缩小 java技术博客
    关于 数据文件自增长 的一点理解
    RAC 实例不能启动 ORA1589 signalled during ALTER DATABASE OPEN
    Linux 超级用户的权利
    RAC 实例 迁移到 单实例 使用导出导入
    Shell 基本语法
    Linux 开机引导与关机过程
    RAC 实例不能启动 ORA1589 signalled during ALTER DATABASE OPEN
    Oracle RAC + Data Guard 环境搭建
  • 原文地址:https://www.cnblogs.com/guangheli/p/11282512.html
Copyright © 2011-2022 走看看