zoukankan      html  css  js  c++  java
  • BZOJ 4373 算术天才⑨与等差数列 线段树+set(恶心死我了)

    mdzz,这道题重构了4遍,花了一个晚上。。。


     满足等差数列的条件:

    1. 假设min是区间最小值,max是区间最大值,那么 max-min+k(r−l)

    2. 区间相邻两个数之差的绝对值的gcd=k

    3. 区间没有重复的数

    前两个条件直接线段树就好啦;而第三个条件:对于每个权值开个set,值为位置(离散化)然后维护一个pp[i],表示当前a[i]这个值,在i前面最后一次出现的位置。

    那么满足第3个条件,当且仅当区间[l,r]的 max { pre[ i ] } ( l <= i <= r ) 小于l,这个也是用线段树维护。 

    最后看修改操作:在set上找前一个数,后一个数,然后修改相应的pre值。 

    #include<cstdio>
    #include<iostream>
    #include<map>
    #include<set>
    #define R register int
    #define pc(x) putchar(x)
    #define ls (tr<<1)
    #define rs (tr<<1|1)
    using namespace std;
    const int N=300010,M=1050000;
    int n,m,cnt,num,mod,G,mmn,mmx;
    int mn[M],mx[M],pp[M],gg[M],a[N],b[N],pos[N],d[N];
    bool flg;
    map<int,int>mp;
    set<int>s[N<<1];
    set<int>::iterator pre,nxt;
    inline int g() {
        R ret=0; register char ch; while(!isdigit(ch=getchar())) ;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret;
    }
    inline int abs(int a) {return a>0?a:-a;}
    inline int gcd(int a,int b) {return b?gcd(b,a%b):a;}
    inline int calc(int x) { R ret;
        if(mp.find(x)==mp.end()) ret=mp[x]=++cnt; else return mp[x];
        s[ret].insert(0),s[ret].insert(n+1); return ret;
    }
    inline void build(int tr,int l,int r) {
        if(l==r) {mn[tr]=mx[tr]=a[l]; pp[tr]=pos[l]; gg[tr]=d[l]; return ;}
        R md=(l+r)>>1; build(ls,l,md),build(rs,md+1,r);
        mn[tr]=min(mn[ls],mn[rs]),mx[tr]=max(mx[ls],mx[rs]);
        pp[tr]=max(pp[ls],pp[rs]),gg[tr]=gcd(gg[ls],gg[rs]);
    }
    inline void updatep(int tr,int l,int r,int pos,int p) {
        if(l==r) {pp[tr]=p; return ;} R md=(l+r)>>1;
        if(pos<=md) updatep(ls,l,md,pos,p); else updatep(rs,md+1,r,pos,p);
        pp[tr]=max(pp[ls],pp[rs]);
    }
    inline void updateg(int tr,int l,int r,int pos,int G) {
        if(l==r) {gg[tr]=G; return;} R md=(l+r)>>1;
        if(pos<=md) updateg(ls,l,md,pos,G); else updateg(rs,md+1,r,pos,G);
        gg[tr]=gcd(gg[ls],gg[rs]);
    }
    inline void update(int tr,int l,int r,int pos,int inc,int pre) {
        if(l==r) {mn[tr]=mx[tr]=inc; pp[tr]=pre; return ;} R md=(l+r)>>1;
        if(pos<=md) update(ls,l,md,pos,inc,pre); else update(rs,md+1,r,pos,inc,pre);
        mn[tr]=min(mn[ls],mn[rs]),mx[tr]=max(mx[ls],mx[rs]),pp[tr]=max(pp[ls],pp[rs]);
    }
    inline void ask(int tr,int l,int r,int LL,int RR) {
        if(LL<=l&&r<=RR) {mmn=min(mmn,mn[tr]),mmx=max(mmx,mx[tr]); if(pp[tr]>=LL) flg=1; return;}
        R md=(l+r)>>1; if(LL<=md) ask(ls,l,md,LL,RR); if(RR>md) ask(rs,md+1,r,LL,RR);
    }
    inline void askg(int tr,int l,int r,int LL,int RR) {
        if(LL<=l&&r<=RR) {G=gcd(gg[tr],G); return ;} R md=(l+r)>>1; 
        if(LL<=md) askg(ls,l,md,LL,RR); if(RR>md) askg(rs,md+1,r,LL,RR); 
    }
    inline bool judge(int l,int r) { 
        if(l==r) return true; flg=false,mmn=0x3f3f3f3f,mmx=G=0;
        ask(1,1,n,l,r); if(!mod) return mmx==mmn; 
        if(flg) return false; 
        if(mmx-mmn!=1ll*(r-l)*mod) return false;
        askg(1,1,n,l,r-1); return G%mod==0;
    }
    signed main() {
        n=g(),m=g();
        for(R i=1;i<=n;i++) {
            a[i]=g(); s[b[i]=calc(a[i])].insert(i);
            pre=s[b[i]].find(i); pos[i]=*(--pre);
        } for(R i=1;i<n;i++) d[i]=abs(a[i]-a[i+1]); build(1,1,n);
        for(R i=1;i<=m;++i) { R k=g(),l=g()^num,r=g()^num;
            if(k&1) {
                pre=nxt=s[b[l]].find(l); pre--,nxt++; 
                if(*nxt<n) updatep(1,1,n,*nxt,*pre);
                s[b[l]].erase(l),b[l]=calc(r),s[b[l]].insert(l);
                pre=nxt=s[b[l]].find(l); pre--,nxt++;
                if(*nxt<n) updatep(1,1,n,*nxt,l); update(1,1,n,l,a[l]=r,*pre);
                if(l>1) updateg(1,1,n,l-1,abs(a[l-1]-r));
                if(l<n) updateg(1,1,n,l,abs(r-a[l+1]));
            } else mod=g()^num,judge(l,r)?(++num,pc('Y'),pc('e'),pc('s')):(pc('N'),pc('o')),pc('
    ');
        }
    }

    2019.04.22 这道题让我想扔掉OI。。。气死我了。。。QAQ

  • 相关阅读:
    spring-session+Redis实现Session共享
    SQLServer语法常用总结
    [PDFBox]后台操作pdf的工具类
    类加载器
    SQLServer常用分页方式
    Tesseract识别图片提取文字&字库训练
    AbstractQueuedSynchronizer的简单介绍
    CountDownLatch 闭锁、FutureTask、Semaphore信号量、Barrier栅栏
    Java线程实现的第三种方式Callable方式与结合Future获取返回值
    原子类型的使用&Unsafe&CAS
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10747988.html
Copyright © 2011-2022 走看看