zoukankan      html  css  js  c++  java
  • #线段树,约数#洛谷 3889 [GDOI2014]吃

    题目

    有一个长度为(n)的数列,现在有(m)组询问每次给出区间([l,r]),查询

    [max_{i,j=1}^n{gcd(a_i,a_j)[(i<l或i>r)且lleq jleq r]} ]


    分析

    首先是离线询问,考虑把(i)拆成两部分处理
    也就是(max{max{ans_{i<l}},max{ans_{i>r}}})
    后面这一坨将数列和询问编号翻转就转换成前面这一坨
    那就按照区间的左端点递增排序,考虑小于左端点的位置所做的贡献,
    处理每个约数下一次出现的位置,如果这个位置出现在区间内,说明这个约数是可以做出贡献的
    那么预处理每个位置的数中每个约数下一次出现的位置,并用线段树维护区间最大值即可


    代码

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #include <cstring>
    #define rr register
    using namespace std;
    const int N=100011;
    struct rec{int l,r,rk;}q[N];
    int n,m,a[N],ir[N],w[N<<2],h[N];
    int ans[N],A[N][131],B[N][131],C[N];
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void print(int ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48);
    }
    bool cmp(rec x,rec y){return x.l<y.l;}
    inline signed max(int a,int b){return a>b?a:b;}
    inline void update(int k,int l,int r,int x,int y){
    	if (l==r) {w[k]=max(w[k],y); return;}
    	rr int mid=(l+r)>>1;
    	if (x<=mid) update(k<<1,l,mid,x,y);
    	    else update(k<<1|1,mid+1,r,x,y);
    	w[k]=max(w[k<<1],w[k<<1|1]);
    }
    inline signed query(int k,int l,int r,int x,int y){
    	if (l==x&&r==y) return w[k];
    	rr int mid=(l+r)>>1;
    	if (y<=mid) return query(k<<1,l,mid,x,y);
    	else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
    	    else return max(query(k<<1,l,mid,x,mid),query(k<<1|1,mid+1,r,mid+1,y));
    }
    inline void doit(){
    	sort(q+1,q+1+m,cmp);
    	memset(h,0,sizeof(h));
    	memset(w,0,sizeof(w));
    	for (rr int i=n,t=0;i;C[i--]=t,t=0)
    	    for (rr int j=1;j<=ir[a[i]];++j)
    	        if (a[i]%j==0){
    		        if (h[j]) A[i][++t]=j,B[i][t]=h[j];
    		        h[j]=i;
    		        if (j*j<a[i]){
    			        if (h[a[i]/j]) A[i][++t]=a[i]/j,B[i][t]=h[a[i]/j];
    			        h[a[i]/j]=i;
    		        }
    	        }
    	for (rr int i=1,j=1;i<=m;++i){
    		for (;j<q[i].l;++j)
    		    for (rr int o=1;o<=C[j];++o)
    		        update(1,1,n,B[j][o],A[j][o]);
    		ans[q[i].rk]=max(ans[q[i].rk],query(1,1,n,q[i].l,q[i].r));
    	}
    }
    signed main(){
    	for (rr int i=1;i<317;++i) ir[i*i]=1;
    	for (rr int i=1;i<N;++i) ir[i]+=ir[i-1];
    	n=iut(); for (rr int i=1;i<=n;++i) a[i]=iut();
    	m=iut(); for (rr int i=1;i<=m;++i) q[i]=(rec){iut(),iut(),i};
    	doit();  for (rr int i=1;i<=m;++i) swap(q[i].l,q[i].r);
    	for (rr int i=1;i<=m;++i) q[i].l=n-q[i].l+1,q[i].r=n-q[i].r+1;
    	reverse(a+1,a+1+n),doit();
    	for (rr int i=1;i<=m;++i) print(ans[i]),putchar(10);
    	return 0;
    }
    
  • 相关阅读:
    (3.4)常用知识-char与varchar的选择
    (3.3)常用知识-索引使用、维护与填充因子
    (3.2)常用知识-字符串处理
    (3.1)常用知识-日期处理
    基于Sql Server 2008的分布式数据库的实践
    将expression转化为数据类型int时发生算术溢出错误
    webserver and application server
    web前端
    linkin
    jquery load
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13819326.html
Copyright © 2011-2022 走看看