• 【刷题】HDU 5869 Different GCD Subarray Query


    Problem Description

    This is a simple problem. The teacher gives Bob a list of problems about GCD (Greatest Common Divisor). After studying some of them, Bob thinks that GCD is so interesting. One day, he comes up with a new problem about GCD. Easy as it looks, Bob cannot figure it out himself. Now he turns to you for help, and here is the problem:

    Given an array (a) of (N) positive integers (a_1, a_2, cdots a_{N-1}, a_N) ; a subarray of (a) is defined as a continuous interval between (a_1) and (a_N) .In other words,(a_i, a_{i+1}, cdots, a_{j-1}, a_j) is a subarray of (a), for (1le ile jle N).For a query in the form ((L, R)) , tell the number of different GCDs contributed by all subarrays of the interval ([L, R]).

    Input

    There are several tests, process till the end of input.

    For each test, the first line consists of two integers (N) and (Q), denoting the length of the array and the number of queries, respectively. (N) positive integers are listed in the second line, followed by (Q) lines each containing two integers (L,R) for a query.

    You can assume that

    (1≤N,Q≤100000)

    (1≤a_i≤1000000)

    Output

    For each query, output the answer in one line.

    Sample Input

    5 3
    1 3 4 6 9
    3 5
    2 5
    1 5

    Sample Output

    6
    6
    6

    Description(CHN)

    给定一个数列,多次询问,每次询问 (L,R),求 ([L,R]) 中所有子区间的 (gcd) 有多少种

    Solution

    预处理对于数列中的每个位置,对于它为 (R) 的所有区间中不同的 (gcd) 出现的最右边的 (L) 是什么。这个东西直接在上一个位置的基础上枚举就好了
    将询问离线
    我们用BIT维护每种 (gcd) 出现的区间的 (L) 的最右的位置在哪里,然后就用差分计算答案就好了

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=300000+10;
    int n,m,a[MAXN],ans[MAXN];
    std::map<int,int> M;
    std::vector< std::pair<int,int> > V[MAXN],query[MAXN];
    struct BIT{
    	int C[MAXN];
    	inline void init()
    	{
    		memset(C,0,sizeof(C));
    	}
    	inline int lowbit(int x)
    	{
    		return x&(-x);
    	}
    	inline void add(int x,int k)
    	{
    		while(x<=n)C[x]+=k,x+=lowbit(x);
    	}
    	inline int sum(int x)
    	{
    		if(!x)return 0ll;
    		int res=0;
    		while(x>0)res+=C[x],x-=lowbit(x);
    		return res;
    	}
    };
    BIT T;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    #define ft first
    #define sd second
    int main()
    {
    	while(scanf("%d%d
    ",&n,&m)!=EOF)
    	{
    		for(register int i=1;i<=n;++i)read(a[i]),V[i].clear(),query[i].clear();
    		T.init();M.clear();
    		V[1].push_back(std::make_pair(1,a[1]));
    		for(register int i=2;i<=n;++i)
    		{
    			int now=a[i];V[i].push_back(std::make_pair(i,a[i]));
    			for(register int j=0,lt=V[i-1].size();j<lt;++j)
    			{
    				std::pair<int,int> pr=V[i-1][j];
    				int d=std::__gcd(now,pr.sd);
    				if(d!=now)V[i].push_back(std::make_pair(pr.ft,d)),now=d;
    			}
    		}
    		for(register int i=1;i<=m;++i)
    		{
    			int l,r;read(l);read(r);
    			query[r].push_back(std::make_pair(i,l));
    		}
    		for(register int i=1;i<=n;++i)
    		{
    			for(register int j=0,lt=V[i].size();j<lt;++j)
    			{
    				std::pair<int,int> pr=V[i][j];
    				if(M[pr.sd])T.add(M[pr.sd],-1);
    				T.add(pr.ft,1);M[pr.sd]=pr.ft;
    			}
    			for(register int j=0,lt=query[i].size();j<lt;++j)
    			{
    				std::pair<int,int> pr=query[i][j];
    				ans[pr.ft]=T.sum(i)-T.sum(pr.sd-1);
    			}
    		}
    		for(register int i=1;i<=m;++i)printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    分析WordPress数据表之用户表(功能篇)
    Android.mk简介:
    win10 mars xlog编译
    sudo apt-get install libstdc++6
    WebRTC 入门教程(二)| WebRTC信令控制与STUN/TURN服务器搭建
    Mars Android 接入指南
    Mars Sample 使用说明
    RxJava2 方法总结
    mqtt client api: 阻塞API
    idea使用git进行项目管理
  • 原文地址:https://www.cnblogs.com/hongyj/p/9562843.html
Copyright © 2020-2023  润新知