zoukankan      html  css  js  c++  java
  • HDU

    No Pain No Game

    题意:给出一个长度为n的1到n的排列 求区间两点gcd最大

    思路:

    因为题目没有更新 我们可以离线求解

    对于每个查询按r排序

    因为两点gcd一定会是两个数的约数 那么可以暴力插入a[i]的约数(当a[x]含有这个约数时 我们就能插入这个约数(x<i))

    我们使用last数组维护上一次出现这个约数的位置即可

    查询:我们就只需要查询l~r出现过最大的约数就行 

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f3f
    const int maxn = 50000+5;
    int Max[maxn<<2],a[maxn],last[maxn],ans[maxn];
    struct node{
        int l,r,id;
        bool friend operator<(const node u,const node v){
            return u.r<v.r;
        }
    }p[maxn];
    void build(int l,int r,int rt){
        Max[rt]=0;
        if(l==r) return ;
        int m=(l+r)>>1;
        build(lson);
        build(rson);
    }
    void push_up(int rt){
        Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
    }
    void update(int l,int r,int rt,int L,int val){
        if(l==r){
            Max[rt]=max(Max[rt],val);
            return ;
        }
        int m=(l+r)>>1;
        if(L<=m) update(lson,L,val);
        else update(rson,L,val);
        push_up(rt);
    }
    int query(int l,int r,int rt,int L,int R){
        if(L<=l&&r<=R) {
            return Max[rt];
        }
        int m=(l+r)>>1;
        int ans=0;
        if(L<=m) ans=max(ans,query(lson,L,R));
        if(R>m)  ans=max(ans,query(rson,L,R));
        return ans;
    }
    int main(){
        int t,n,m;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            memset(last,0,sizeof(last));
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            scanf("%d",&m);
            for(int i=1;i<=m;i++){
                scanf("%d %d",&p[i].l,&p[i].r);
                p[i].id=i;
            }
            sort(p+1,p+1+m);
            int j=1;
            build(1,n,1);
            for(int i=1;i<=n;i++){
                for(int k=1;k*k<=a[i];k++){
                    if(a[i]%k==0){
                        if(last[k])
                            update(1,n,1,last[k],k);
                        if(last[a[i]/k]&&k!=a[i]/k)
                            update(1,n,1,last[a[i]/k],a[i]/k);
                        last[k]=i;
                        last[a[i]/k]=i;
                    }
                }
                while(p[j].r<=i){
                    if(j>m) break;
                    if(p[j].l>p[j].r) ans[p[j].id]=0;
                    else ans[p[j].id]=query(1,n,1,p[j].l,p[j].r);
                    j++;
                }
            }
            for(int i=1;i<=m;i++){
                printf("%d
    ",ans[i]);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    java基础3 循环语句:While 循环语句、do while 循环语句、 for 循环语句 和 break、continue关键字
    java基础2 判断语句:if ... else 语句和 switch 语句
    IT行业经典面试技巧及方法思路。
    Java基础1,入门基础知识
    SVN的使用、分支合并及解决冲突详解
    VC工程产生文件后缀名解释
    ireport报表,打印时,报表加载失败的解决方法
    MySQL 事务、视图、索引
    MySQL高级查询
    MySQL中的主键约束和外键约束
  • 原文地址:https://www.cnblogs.com/MengX/p/11291349.html
Copyright © 2011-2022 走看看