列表

详情


NC15557. 连续区间的最大公约数

描述

给一个数列共n(n<=100,000)个数,a1,a2,...,an.(0<=ai<=1000,000,000).有q(q<=100,000)个询问。每个询问为l,r(1<=l<=r<=n).求gcd(al,al+1,...,ar).
再求区间[l,r]的子区间中(l<=l'<=r'<=r)满足gcd(al,al+1,...,ar) = gcd(al',al'+1,...ar')的子区间个数.

输入描述

第一行一个数T表示数据组数
第二行一个数n
接下来一行n个数,a1,a2,...,an
接下一行一个数q
接下来一行2个数l和r。

输出描述

首先输出一行“Case #:t”,t代表当前是第几组数据。
接下来q行,每行输出2个数,第一个是gcd(al,al+1,...,ar),
第二个是区间[l,r]的子区间中(l<=l'<=r'<=r)满足gcd(al,al+1,...,ar) = gcd(al',al'+1,...ar')的子区间个数。

示例1

输入:

2
5
1 2 4 6 7
4
1 5
2 4
3 4
4 4
5
1 2 4 2 1
6
1 1
1 3
2 2
2 3
2 4
3 3

输出:

Case #1:
1 8
2 4
2 1
6 1
Case #2:
1 1
1 3
2 1
2 2
2 5
4 1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 866ms, 内存消耗: 114636K, 提交时间: 2019-07-28 16:06:01

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define LL long long
#define pb emplace_back
#define pii pair<int, int>

const int N = 1e5 + 5;
int T, n, q, a[N], L[N], R[N], d[N], cnt;
LL ans[N];
vector<int> vc[N], p[N*20];
vector<LL> sum[N*20];
map<int, int> mp, _p, mmp;
int main() {
    scanf("%d", &T);
    for(int cs = 1; cs <= T; ++cs) {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        scanf("%d", &q);
        for (int i = 1; i <= q; ++i) {
            scanf("%d %d", &L[i], &R[i]);
            vc[R[i]].pb(i);
        }
        cnt = 0;
        for (int i = 1; i <= n; ++i) {
            for (auto it : mp) {
                int g = __gcd(it.fi, a[i]);
                if(_p.find(g) == _p.end()) _p[g] = it.se;
            }
            if(_p.find(a[i]) == _p.end()) _p[a[i]] = i;
            mp = _p;
            _p.clear();
            vector<pii> tmp;
            for (auto it : mp) tmp.pb(it.se, it.fi);
            for (int j = 0; j < tmp.size(); ++j) {
                if(j+1 == tmp.size()) tmp[j].fi = i;
                else tmp[j].fi = tmp[j+1].fi-1;
                int now;
                if(mmp.find(tmp[j].se) == mmp.end()) {
                    mmp[tmp[j].se] = ++cnt;
                    now = cnt;
                }
                else now = mmp[tmp[j].se];
                p[now].pb(tmp[j].fi);
                sum[now].pb(sum[now].size()==0?tmp[j].fi:sum[now].back()+tmp[j].fi);
            }
            for (int x : vc[i]) {
                int l = L[x];
                int t = lower_bound(tmp.begin(), tmp.end(), pii{l, 0})-tmp.begin();
                d[x] = tmp[t].se;
                int pp = mmp[d[x]];
                t = lower_bound(p[pp].begin(), p[pp].end(), l)-p[pp].begin();
                if(t-1>=0) ans[x] = sum[pp].back()-sum[pp][t-1]-(sum[pp].size()-t)*1LL*(l-1);
                else ans[x] = sum[pp].back()-sum[pp].size()*1LL*(l-1);
            }
        }
        printf("Case #%d:\n", cs);
        for (int i = 1; i <= q; ++i) printf("%d %lld\n", d[i], ans[i]);
        for (auto it : mmp) p[it.se].clear(), sum[it.se].clear();
        mmp.clear();
        mp.clear();
        for (int i = 1; i <= n; ++i) vc[i].clear();
    }
    return 0;
}

C++ 解法, 执行用时: 554ms, 内存消耗: 47992K, 提交时间: 2022-03-15 23:03:54

#include<bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define fi first
#define se second
#define mp make_pair
using namespace std;
int T,n,a[100005],q;
struct que{
	int l,r,id;
}A[100005];
int P[100005][35],Ln[100005],D[100005][35];
map<int,int> G;
map<int,ll> Gi;
vector<PII> F[100005];
int Pi[100005],di[100005];
ll L,R,S,X,Ans[100005],d[100005];
int ans[100005];

int read(){
	int x=0;char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x;
}

void print(ll x){
	if(x>=10) print(x/10);
	putchar(x%10+'0');
}

int cmp(que u,que v){
	return u.r<v.r;
}

void add(int x,int y){
	while(x<=n) d[x]+=y,x+=x&-x;
}

ll query(int x){
	ll res=0;
	while(x) res+=d[x],x-=x&-x;
	return res;
}

int main(){
	T=read();
	for(int o=1;o<=T;o++){
		G.clear();
		Gi.clear();
		n=read();
		for(int i=1;i<=n;i++) F[i].clear();
		for(int i=1;i<=n;i++) a[i]=read();
		q=read();
		for(int i=1;i<=q;i++) A[i].l=read(),A[i].r=read(),A[i].id=i;
		sort(A+1,A+q+1,cmp);
		Ln[n]=1,P[n][1]=n,D[n][1]=a[n];
		for(int i=n-1;i>=1;i--){
			Ln[i]=1,P[i][1]=i,D[i][1]=a[i];
			for(int j=1,v;j<=Ln[i+1];j++){
				v=__gcd(D[i+1][j],a[i]);
				if(v!=D[i][Ln[i]]) Ln[i]++,P[i][Ln[i]]=P[i+1][j],D[i][Ln[i]]=v;
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=Ln[i];j++) F[P[i][j]].push_back(mp(i,D[i][j])); 
		}
		int las=0;
		for(int i=1;i<=n;i++) d[i]=0;
		for(int i=1;i<=q;i++){
			for(int j=las+1,sz;j<=A[i].r;j++){
				sz=F[j].size();
				for(int k=0,v;k<sz;k++){
					v=F[j][k].fi;
					if(v!=j) G[Pi[v]]--,Gi[Pi[v]]-=v,add(v,-di[v]);
					Pi[v]=F[j][k].se;
					G[Pi[v]]++,Gi[Pi[v]]+=v,di[v]=j;
					add(v,j);
				}
			}
			ans[A[i].id]=Pi[A[i].l];
			S=Gi[Pi[A[i].l]],X=G[Pi[A[i].l]];
			L=(2ll*S/X+1-X)/2,R=L+X-1;
			if(L<A[i].l) X-=(A[i].l-L),L=A[i].l;
			Ans[A[i].id]=1ll*X*(A[i].r+1)-query(R)+query(L-1);
			las=A[i].r;
		}
		printf("Case #%d:\n",o);
		for(int i=1;i<=q;i++) print(ans[i]),putchar(' '),print(Ans[i]),puts("");
	}

	return 0;
}

上一题