• BZOJ4028 HEOI2015公约数数列(分块)


      前缀gcd的变化次数是log的,考虑对每一种gcd查询,问题变为查询一段区间是否存在异或前缀和=x/gcd。

      无修改的话显然可以可持久化trie,但这玩意实在没法支持修改。于是考虑分块。

      对于每一块将其中所有块内异或前缀和排序。查询时先看这块与上一块相比gcd有没有变化,如果有对其中每个位置暴力查询,否则在排序后的数组中二分。修改时暴力改每一块的前缀gcd及异或和,被修改的块暴力重构排序数组即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100010
    #define ll long long
    ll read()
    {
        ll x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,a[N];
    int block_size,block_tot,L[N],R[N],pos[N];
    int gcd_pre[N],xor_pre[N],gcd_block[N],xor_block[N];
    struct data
    {
        int x,i;
        bool operator <(const data&a) const
        {
            return x<a.x||x==a.x&&i<a.i;
        }
    }v[N];
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4028.in","r",stdin);
        freopen("bzoj4028.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        for (int i=1;i<=n;i++) a[i]=read();
        block_size=sqrt(n);block_tot=(n-1)/block_size+1;
        for (int i=1;i<=block_tot;i++)
        L[i]=(i-1)*block_size+1,R[i]=min(n,i*block_size);
        for (int i=1;i<=block_tot;i++)
        {
            for (int j=L[i];j<=R[i];j++)
            gcd_block[i]=gcd(gcd_block[i],a[j]),
            xor_block[i]=xor_block[i]^a[j],
            pos[j]=i;
            gcd_pre[i]=gcd(gcd_pre[i-1],gcd_block[i]),xor_pre[i]=xor_pre[i-1]^xor_block[i];
        }
        for (int i=1;i<=block_tot;i++)
        {
            v[L[i]].x=a[L[i]],v[L[i]].i=L[i];
            for (int j=L[i]+1;j<=R[i];j++)
            v[j].x=v[j-1].x^a[j],v[j].i=j;
            sort(v+L[i],v+R[i]+1);
        }
        m=read();
        while (m--)
        {
            char c=getchar();
            while (c<'A'||c>'Z') c=getchar();
            if (c=='M')
            {
                int p=read()+1,x=read();a[p]=x;p=pos[p];
                gcd_block[p]=xor_block[p]=0;
                for (int i=L[p];i<=R[p];i++)
                gcd_block[p]=gcd(gcd_block[p],a[i]),
                xor_block[p]=xor_block[p]^a[i];
                for (int i=p;i<=block_tot;i++)
                gcd_pre[i]=gcd(gcd_pre[i-1],gcd_block[i]),
                xor_pre[i]=xor_pre[i-1]^xor_block[i];
                v[L[p]].x=a[L[p]],v[L[p]].i=L[p];
                for (int i=L[p]+1;i<=R[p];i++)
                v[i].x=v[i-1].x^a[i],v[i].i=i;
                sort(v+L[p],v+R[p]+1);
            }
            else
            {
                ll x=read();int ans=0;
                for (int i=1;i<=block_tot;i++)
                {
                    if (ans) break;
                    if (gcd_pre[i]==gcd_pre[i-1])
                    {
                        if (x%gcd_pre[i-1]==0)
                        {
                            int l=L[i],r=R[i];
                            while (l<=r)
                            {
                                int mid=l+r>>1;
                                if (v[mid].x>=(x/gcd_pre[i-1]^xor_pre[i-1])) ans=mid,r=mid-1;
                                else l=mid+1;
                            }
                            if (ans&&v[ans].x==(x/gcd_pre[i-1]^xor_pre[i-1])) {ans=v[ans].i;break;}
                            else ans=0;
                        }
                    }
                    else
                    {
                        int p=gcd_pre[i-1],q=xor_pre[i-1];
                        for (int j=L[i];j<=R[i];j++)
                        {
                            p=gcd(p,a[j]),q^=a[j];
                            if (x%p==0&&x/p==q) {ans=j;break;}
                        }
                    }
                }
                if (ans) printf("%d
    ",ans-1);
                else printf("no
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    windows 7中添加新硬件的两种方法(本地回环网卡)
    文档编辑大神
    BIOS Setup
    Sound Card Chip
    modem&NIC&sound card
    Monitor
    chassis & power
    HDD
    C#开发实例 鼠标篇
    编程之美 1.8小飞的电梯调度算法
  • 原文地址:https://www.cnblogs.com/Gloid/p/9825326.html
Copyright © 2020-2023  润新知