题意:
有一个长度为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\n",ans); } return 0; }
来源:https://www.cnblogs.com/1124828077ccj/p/12257659.html