zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    mysql 游标查询
    mysql忘记root密码的解决
    java 两种缓存
    java 实现缓存
    android ndk
    本地计算机上的 MSSQLSERVER 服务启动后又停止了。一些服务自动停止,如果它们没有什么可做的,例如“性能日志和警报”服务 [解决办法]
    选择WEB开发语言
    linux 查看硬件信息
    java 缓存 谈
    程序员相关
  • 原文地址:https://www.cnblogs.com/Gloid/p/9825326.html
Copyright © 2011-2022 走看看