[bzoj4373]算术天才⑨与等差数列

来自FallDream的博客,未经允许,请勿转载,谢谢。


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

第一行包含两个正整数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的个数来进行解密。

 

只想到一个比较麻烦的判断方式

一个序列合法,当且仅当最小/最大值/权值和合法,没有相同元素且差分的gcd是k。

除了没有相同元素这个条件,其他的都能线段树求。

考虑每种权值维护一棵平衡树,然后线段树维护区间 每一个位置和她相同的上一个格子的位置 的最大值,如果这个最大值小于l,那么就没有相同元素。

常数巨大。

除了gcd以外其他都是严格nlogn的 区间gcd复杂度我不知道是什么 感觉是nlogn但是不会证。。

另:300题打卡。

#include<iostream>
#include<cstdio>
#include<map>
#include<set>
#define ll long long
#define MN 300000
#define N 524288
#define It set<int>::iterator
using namespace std;
inline long long read()
{
    long long x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

struct data{int mx,mn;ll sum;
    friend data operator +(data a,data b){return(data){max(a.mx,b.mx),min(a.mn,b.mn),a.sum+b.sum};}
};
struct Tree{int l,r;data x;}T[MN*4+5];
int t[N*2+5],t2[N*2+5],cnt=0,a[MN+5],last=0,n,m;
set<int> st[MN*2+5];
map<int,int> mp;
inline int gcd(int x,int y){return !y?x:gcd(y,x%y);}
inline int abs(int x){return x<0?-x:x;}

int Query2(int l,int r)
{
    int res=0;
    for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1)
    {
        if(~l&1) res=gcd(res,t2[l+1]);
        if( r&1) res=gcd(res,t2[r-1]);
    }
    return res;
}

void Modify2(int x,int ad)
{
    t2[x+=N]=ad;
    for(x>>=1;x;x>>=1) t2[x]=gcd(t2[x<<1],t2[x<<1|1]);
}

int Query(int l,int r)
{
    int res=0;
    for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1)
    {
        if(~l&1) res=max(res,t[l+1]);
        if( r&1) res=max(res,t[r-1]);
    }
    return res;
}

void Modify(int x,int ad)
{
    t[x+=N]=ad;
    for(x>>=1;x;x>>=1) t[x]=max(t[x<<1],t[x<<1|1]);
}

void Build(int x,int l,int r)
{
    if((T[x].l=l)==(T[x].r=r)) {T[x].x=(data){a[l],a[l],a[l]};return;}
    int mid=l+r>>1;
    Build(x<<1,l,mid);Build(x<<1|1,mid+1,r);
    T[x].x=T[x<<1].x+T[x<<1|1].x;
}

void Modify(int x,int k,int v)
{
    if(T[x].l==T[x].r) T[x].x=(data){v,v,v};
    else
    {
        int mid=T[x].l+T[x].r>>1;
        if(k<=mid) Modify(x<<1,k,v);
        else Modify(x<<1|1,k,v);
        T[x].x=T[x<<1].x+T[x<<1|1].x;
    }
}

data Query(int x,int l,int r)
{
    if(T[x].l==l&&T[x].r==r) return T[x].x;
    int mid=T[x].l+T[x].r>>1;
    if(r<=mid) return Query(x<<1,l,r);
    else if(l>mid) return Query(x<<1|1,l,r);
    else return Query(x<<1,l,mid)+Query(x<<1|1,mid+1,r);
}

int main()
{
    n=read();m=read();
    for(int i=1;i<=n;++i)
    {
        !mp[a[i]=read()]?mp[a[i]]=++cnt:0;
        int x=mp[a[i]];
        if(st[x].begin()!=st[x].end()) Modify(i,*(--st[x].end()));
        st[x].insert(i);
        if(i>1) Modify2(i-1,abs(a[i]-a[i-1]));
    }
    Build(1,1,n);
    for(int i=1;i<=m;++i)
    {
        int op=read();
        if(op==1)
        {
            int x=read()^last,y=read()^last;
            if(a[x]==y) continue;
            if(x!=n) Modify2(x,abs(a[x+1]-y));
            if(x!=1) Modify2(x-1,abs(y-a[x-1]));
            int ha=mp[a[x]];
            It it=st[ha].lower_bound(x),it2=it;
            if(++it!=st[ha].end()) Modify(*it,(it2==st[ha].begin()?0:*(--it2)));
            st[ha].erase(--it);
            !mp[y]?mp[y]=++cnt:0;ha=mp[y];
            it=st[ha].lower_bound(x),it2=it;
            if(it!=st[ha].end()) Modify(*it,x);
            if(it2!=st[ha].end()&&it2!=st[ha].begin())
                Modify(x,*(--it2));
            else Modify(x,0);
            a[x]=y;Modify(1,x,y);st[ha].insert(x);
        }
        else
        {
            int l=read()^last,r=read()^last,k=read()^last;
            data x=Query(1,l,r);bool flag=0;
            if(l==r) {puts("Yes"),++last;continue;}
            if(!k)
            {
                if(x.mn==x.mx) puts("Yes"),++last;
                else puts("No");
                continue;
            }
            if(x.sum!=1LL*x.mn*(r-l+1)+1LL*(r-l+1)*(r-l)/2*k) flag=1;
            else if(x.mx!=x.mn+1LL*(r-l)*k) flag=1;
            else
            {
                int Gcd=Query2(l,r-1),MxLast=Query(l,r);
                if(Gcd!=k||MxLast>=l) flag=1;
            }
            if(flag) puts("No");
            else puts("Yes"),++last;
        }
    }
    return 0;
}
posted @ 2017-06-04 00:34  FallDream  阅读(488)  评论(0编辑  收藏  举报