zoukankan      html  css  js  c++  java
  • dtoi4702 Gcd

    题意:

         有一个长度为n的互不相同的序列,求对于任意i,j,1<=i<=j<=n,求g(i,j)。

         g(i,j)的定义是将i~j的元素都删除之后剩余的数字两两之间gcd的最大值。

    题解:

         首先枚举gcd,考虑什么时候会作为答案。

         找到它的倍数所在的位置,假设从小到大所在的位置为a[0],a[1]...a[k],那么只需要有a[0],a[1]存在或者a[k-1],a[k]存在或者a[0],a[k]存在,然后其它区间乱删都没有关系。

         那么现在的问题就在于“区间乱删”时,会有好多之前已经计算过的答案被算了多次,显然是不行的。

         仔细思考我们要解决什么问题,现在我们需要做的事情就是给定一个区间l,r求l,r中剩余的子区间还有多少个。

         那我们先对于每一个位置i,记t[i]表示[i,i],[i,i+1]...[i,t[i]]这些区间已经被算过了。不难发现t[i]是单调的,因为如果大区间算过了,小区间一定也被算过了。

         那么l,r中剩余的子区间还有多少个要如何计算呢,其实答案就是[l,r]中,对于所有满足(t[i]<=r)的i,r-t[i]的总和。由于t[i]是单调的,所以在线段树上二分一下再求个和就行了。

         接下来我们把[l,r]中所有t[i]<=r的设置为t[i]=r,这依然可以线段树解决。于是就做完了这道题。

    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    const int INF=1e9;
    int T,n,a[200002],min1[200002],min2[200002],max1[200002],max2[200002];
    typedef struct{
        int Min,f;
        long long sum;
    }P;
    P p[800002];
    long long ans;
    void build(int root,int begin,int end){
        if (begin==end)
        {
            p[root].Min=p[root].sum=begin-1;
            p[root].f=0;return;
        }
        int mid=(begin+end)/2;
        build(root*2,begin,mid);build(root*2+1,mid+1,end);
        p[root].Min=min(p[root*2].Min,p[root*2+1].Min);
        p[root].sum=p[root*2].sum+p[root*2+1].sum;
        p[root].f=0;
    }
    void pushdown(int root,int begin,int mid,int end){
        if (p[root].f)
        {
            p[root*2].Min=p[root].f;p[root*2+1].Min=p[root].f;
            p[root*2].sum=(long long)p[root].f*(mid-begin+1);p[root*2+1].sum=(long long)p[root].f*(end-mid);
            p[root*2].f=p[root].f;p[root*2+1].f=p[root].f;
            p[root].f=0;
        }
    }
    void gengxin(int root,int begin,int end,int begin2,int end2,int wz){
        if (begin>end2 || end<begin2)return;
        if (begin>=begin2 && end<=end2)
        {
            p[root].Min=p[root].f=wz;
            p[root].sum=(long long)wz*(end-begin+1);
            return;
        }
        int mid=(begin+end)/2;pushdown(root,begin,mid,end);
        gengxin(root*2,begin,mid,begin2,end2,wz);gengxin(root*2+1,mid+1,end,begin2,end2,wz);
        p[root].Min=min(p[root*2].Min,p[root*2+1].Min);
        p[root].sum=p[root*2].sum+p[root*2+1].sum;
    }
    int cx(int root,int begin,int end,int z){
        if (begin==end)return begin;
        int mid=(begin+end)/2;pushdown(root,begin,mid,end);
        if (p[root*2+1].Min<=z)return cx(root*2+1,mid+1,end,z);
        else return cx(root*2,begin,mid,z);
    }
    int chaxun(int root,int begin,int end,int begin2,int end2){
        if (begin>end2 || end<begin2)return begin2-1;
        if (begin>=begin2 && end<=end2)
        {
            if (p[root].Min<=end2)return cx(root,begin,end,end2);
            return begin2-1;
        }
        int mid=(begin+end)/2;pushdown(root,begin,mid,end);
        int t1=chaxun(root*2+1,mid+1,end,begin2,end2);
        if (t1>=begin2)return t1;
        else return chaxun(root*2,begin,mid,begin2,end2);
    }
    long long cxsum(int root,int begin,int end,int begin2,int end2){
        if (begin>end2 || end<begin2 || begin2>end2)return 0;
        if (begin>=begin2 && end<=end2)return p[root].sum;
        int mid=(begin+end)/2;pushdown(root,begin,mid,end);
        return cxsum(root*2,begin,mid,begin2,end2)+cxsum(root*2+1,mid+1,end,begin2,end2); 
    }
    long long js(int x,int y){
        if (x<0 || x>n || y<0 || y>n || x==y)return 0;
        long long ans=0;
        if (x>1)
        {
            int ef=chaxun(1,1,n,1,x-1);
            ans+=((long long)(x-1)*ef-cxsum(1,1,n,1,ef));
            gengxin(1,1,n,1,ef,x-1);
        }
        if (x+1<=y-1)
        {
            int ef=chaxun(1,1,n,x+1,y-1);
            ans+=((long long)(y-1)*(ef-x)-cxsum(1,1,n,x+1,ef));
            gengxin(1,1,n,x+1,ef,y-1);
        }
        if (y<n)
        {
            int ef=chaxun(1,1,n,y+1,n);
            ans+=((long long)n*(ef-y)-cxsum(1,1,n,y+1,ef));
            gengxin(1,1,n,y+1,ef,n);
        }
        
        return ans;
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);int Max=0;ans=0;
            for (int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                Max=max(Max,a[i]);
            }
            for (int i=1;i<=Max;i++)
            {
                min1[i]=min2[i]=INF;
                max1[i]=max2[i]=-INF;
            }
            for (int i=1;i<=n;i++)
            {
                if (min1[a[i]]==INF)min1[a[i]]=i;
                else if (min2[a[i]]==INF)min2[a[i]]=i;
            }
            for (int i=n;i>=1;i--)
            {
                if (max1[a[i]]==-INF)max1[a[i]]=i;
                else if (max2[a[i]]==-INF)max2[a[i]]=i;
            }
            build(1,1,n);
            for (int i=Max;i>=1;i--)
            {
                int mi1=INF,mi2=INF,mx1=-INF,mx2=-INF;
                for (int j=i;j<=Max;j+=i)
                {
                    if (min1[j]<mi1)
                    {
                        mi2=mi1;mi1=min1[j];
                    }
                    else mi2=min(mi2,min1[j]);
                    if (min2[j]<mi1)
                    {
                        mi2=mi1;mi1=min2[j];
                    }
                    else mi2=min(mi2,min2[j]);
                    if (max1[j]>mx1)
                    {
                        mx2=mx1;mx1=max1[j];
                    }
                    else mx2=max(mx2,max1[j]);
                    if (max2[j]>mx1)
                    {
                        mx2=mx1;mx1=max2[j];
                    }
                    else mx2=max(mx2,max2[j]);
                }
                ans+=i*(js(mx2,mx1)+js(mi1,mx1)+js(mi1,mi2));
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    CentOS安装配置ganglia
    k-means聚类算法
    SharePoint solution and feature management with PowerShell
    EM算法
    极客”一词,来自于美国俚语“geek”的音译,一般理解为性格古怪的人
    学习游戏要学习编程语言吗?十大主流编程语言解析
    platform_device与platform_driver
    《用户体验要素》澄清了 UI 原型设计中看不见确感受得到的那一层
    ipconfig /flushdns 清除系统DNS缓存
    typedef和define具体的具体差别
  • 原文地址:https://www.cnblogs.com/1124828077ccj/p/12257659.html
Copyright © 2011-2022 走看看