zoukankan      html  css  js  c++  java
  • 【BZOJ4028】[HEOI2015]公约数数列(分块)

    【BZOJ4028】[HEOI2015]公约数数列(分块)

    题面

    BZOJ
    洛谷

    题解

    看一道题目就不会做系列
    首先(gcd)最多只会有(log)种取值,所以我们可以暴力枚举出所有可能的(gcd)
    那么我们现在按照步骤要解决两个问题。第一个是怎么动态维护(gcd)的取值,第二个是怎么动态维护异或和。
    我们考虑分块。
    只维护块内的前缀(gcd)和前缀异或和,这样子每次修改只需要暴力重构块。
    每次询问的时候如果块内的(gcd)不变,那么二分答案,找找有没有满足条件的异或和。
    否则直接暴力扫这一块。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    #define MAX 100100
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    const int blk=400;
    int L[blk],R[blk];
    int g[MAX],s[MAX],a[MAX];
    struct Data{int id,v;}b[MAX];
    bool operator<(Data a,Data b){if(a.v!=b.v)return a.v<b.v;return a.id<b.id;}
    void Build(int p)
    {
    	g[L[p]]=s[L[p]]=a[L[p]];
    	for(int i=L[p]+1;i<=R[p];++i)
    	{
    		g[i]=__gcd(g[i-1],a[i]);
    		s[i]=s[i-1]^a[i];
    	}
    	for(int i=L[p];i<=R[p];++i)b[i]=(Data){i,s[i]};
    	sort(&b[L[p]],&b[R[p]+1]);
    }
    int n,bel[MAX];
    char ch[10];
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)bel[i]=(i-1)/blk+1;
    	for(int i=1;i<=n;++i)if(!L[bel[i]])L[bel[i]]=i;
    	for(int i=1;i<=n;++i)R[bel[i]]=i;
    	for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=1;i<=bel[n];++i)Build(i);
    	int Q=read();
    	while(Q--)
    	{
    		scanf("%s",ch);
    		if(ch[0]=='M')
    		{
    			int x=read()+1,y=read();
    			a[x]=y;Build(bel[x]);
    		}
    		else
    		{
    			ll x;scanf("%lld",&x);
    			int D=a[1],ans=-1,X=0;
    			for(int i=1;i<=bel[n]&&ans==-1;++i)
    				if(__gcd(D,g[R[i]])==D)
    				{
    					if(x%D==0)
    					{
    						ll k=(x/D)^X;
    						int l=L[i],r=R[i],ret=l;
    						while(l<=r)
    						{
    							int mid=(l+r)>>1;
    							if(b[mid].v>=k)ret=mid,r=mid-1;
    							else l=mid+1;
    						}
    						if(b[ret].v==k){ans=b[ret].id;break;}
    					}
    					D=__gcd(D,g[R[i]]);X^=s[R[i]];
    				}
    				else
    					for(int j=L[i];j<=R[i];++j)
    					{
    						D=__gcd(D,a[j]);X^=a[j];
    						if(1ll*D*X==x){ans=j;break;}
    					}
    			if(!~ans)puts("no");
    			else printf("%d
    ",ans-1);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    centos 修改语言、时区
    去除 ufeff
    Docker介绍及使用
    消息队列
    数据结构与算法
    Haystack
    Python面向对象之魔术方法
    关于Redis处理高并发
    Redis
    RESTful规范
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10771584.html
Copyright © 2011-2022 走看看