BZOJ4028&&洛谷P4108 [HEOI2015]公约数数列

分块大法好


代码

//By AcerMo
#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1e5+7;
int a[maxn],n,m;
int l[1000],r[1000];
int block,cnt,bloc[maxn];
int Gcd[maxn],Xor[maxn];
set<int>S[990];
inline int gcd(int a,int b)
{
    if(!b)return a;
    return gcd(b,a%b);
}
inline int read()
{
	int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}
inline void build(int x)
{
    S[x].clear();
    Gcd[l[x]]=a[l[x]],Xor[l[x]]=a[l[x]];
    S[x].insert(Xor[l[x]]);
    for(int i=l[x]+1;i<=r[x];i++)
    {
        Gcd[i]=gcd(Gcd[i-1],a[i]),Xor[i]=Xor[i-1]^a[i];
        S[x].insert(Xor[i]);
    }
    return ;
}
int main()
{
    n=read();block=sqrt(n);
    for(int i=1;i<=n;i++) a[i]=read();
    if(n%block) cnt=n/block+1;
    else cnt=n/block;
    for(int i=1;i<=cnt;i++)
        l[i]=(i-1)*block+1,r[i]=i*block;
    r[cnt]=n;
    for(int i=1;i<=n;i++)
        bloc[i]=(i-1)/block+1;
    for(int i=1;i<=cnt;i++) build(i);
    m=read();
    for (int i=1;i<=m;i++)
    {
        char s[10];
        scanf("%s",s);
        if(s[0]=='M')
        {
            int x,y;
            scanf("%d%d",&x,&y);x++;
            a[x]=y;build(bloc[x]);
        }
        else
        {
            long long int x;scanf("%lld",&x);
            int flag=0,lg=0,lx=0;
            for(int i=1;i<=cnt;i++)
            {
                int T=gcd(lg,Gcd[r[i]]);
                if(T!=lg)
                {
                    for(int j=l[i];j<=r[i];j++)
                        if((long long)(Xor[j]^lx)*(long long)(gcd(lg,Gcd[j]))==x)
                        	{flag=j;break;}
                    if(flag>0)break;
                }
                else
                {
                    if(x%T==0&&S[i].count((int)(x/T)^lx))
                    {
                        for(int j=l[i];j<=r[i];j++)
                            if((long long)(Xor[j]^lx)*(long long)(gcd(lg,Gcd[j]))==x)
                            	{flag=j;break;}
                        if(flag>0)break;
                    }
                }
                lg=T,lx^=Xor[r[i]];
            }
            if(flag>0) printf("%d\n",flag-1);
            else puts("no");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/81022980