[ICPC 2024 Chengdu R] Good Partitions题解

P15080 [ICPC 2024 Chengdu R] Good Partitions

题目描述

Lawliet 拥有一个长度为 nnn 的数字序列 a1,a2,…,ana_1, a_2, \ldots, a_na1,a2,,an,他希望知道「好数字」的个数。

定义一个整数 kkk 是「好数字」,如果它满足以下条件:

  • 1≤k≤n1 \leq k \leq n1kn
  • 将序列 aaa 依据 kkk 按照以下划分方法分成若干份后,每一份序列都是单调不降的。

划分方法为:

  • 将序列 aaa 分成 ⌈nk⌉\lceil \frac{n}{k} \rceilkn 份;
  • 对于第 iii 份(1≤i≤⌈nk⌉−11 \leq i \leq \lceil \frac{n}{k} \rceil - 11ikn1),包含的元素是 a(i−1)×k+1,a(i−1)×k+2,…,ai×ka_{(i - 1) \times k + 1}, a_{(i - 1) \times k + 2}, \ldots, a_{i \times k}a(i1)×k+1,a(i1)×k+2,,ai×k
  • 对于第 ⌈nk⌉\lceil \frac{n}{k} \rceilkn 份,包含的元素是 a(⌈nk⌉−1)×k+1,…,ana_{(\lceil \frac{n}{k} \rceil - 1) \times k + 1}, \ldots, a_na(⌈kn1)×k+1,,an

Lawliet 认为这个问题太过简单了,于是他会进行 qqq 次修改,每次修改会给出两个正整数 pppvvv,然后将 apa_pap 的数值修改为 vvv

Lawliet 需要你帮助计算,对于未进行任何修改前以及序列 aaa 每次修改后,满足上述条件的「好数字」的个数。

输入格式

第一行包含一个整数 ttt1≤t≤101\le t\le 101t10),代表测试组数。

对于每组测试数据,第一行包含两个整数 nnn1≤n≤2⋅1051 \le n \le 2 \cdot 10^51n2105)和 qqq1≤q≤2⋅1051 \le q \le 2 \cdot 10^51q2105),分别表示序列的长度和修改次数。

第二行包含 nnn 个整数,表示序列 a1,a2,…,ana_1, a_2, \ldots, a_na1,a2,,an1≤ai≤2⋅1091\le a_i\le 2\cdot 10^91ai2109)。

接下来的 qqq 行,每行包含两个整数 ppp1≤p≤n1 \le p \le n1pn)和 vvv1≤v≤2⋅1091 \le v \le 2 \cdot 10^91v2109),表示将序列中的第 ppp 个位置的元素修改为 vvv

单个测试点中 nnn 之和与 qqq 之和均不超过 2⋅1052\cdot 10^52105

输出格式

对于每组测试数据,输出 q+1q + 1q+1 行,分别代表未进行任何修改前以及序列 aaa 每次修改后,序列中的「好数字」的个数。

输入输出样例 #1

输入 #1

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

输出 #1

1
2
3

思路

可以发现,值为上升的所有段的gcd,线段树维护即可。

代码见下

#include<bits/stdc++.h> 
using namespace std;
int t,n,q,a[200005],pp,uu,te[800005],d[200005];
inline int gcd(int a,int b){
	if(a==0||b==0){
		return max(a,b);
	}
	else{
		return __gcd(a,b);
	}
}
inline void bu(int a1,int l,int r){
	if(l==r){
		if(a[l]>=a[l+1]+1){
			te[a1]=l;
		}
		else{
			te[a1]=0;
		}
		return ;
	}
	int mid=(l+r)/2;
	bu(a1*2,l,mid);
	bu(a1*2+1,mid+1,r);
	te[a1]=gcd(te[a1*2],te[a1*2+1]);
	return ;
}
inline void ci(int a1,int l,int r,int x,int v){
	if(l>=x&&r<=x){
		te[a1]=v;
		return ;
	}
	int mid=(l+r)/2;
	if(x<=mid){
		ci(a1*2,l,mid,x,v);
	}
	else{
		ci(a1*2+1,mid+1,r,x,v);
	}
	te[a1]=gcd(te[a1*2],te[a1*2+1]);
	return ;
}
int main(){
	cin>>t;
	for(int i=1;i<=200000;i++){
		for(int j=1;j*j<=i;j++){
			if(i%j==0){
				d[i]++;
				if(j*j!=i){
					d[i]++;
				}
			}
		}
	}
	while(t--){
		cin>>n>>q;
		d[0]=n;
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}
		if(n==1){
			cout<<1<<'\n';
			while(q--){
				cin>>pp>>uu;
				cout<<1<<'\n';
			}
			continue;
		}
		bu(1,1,n-1);
		cout<<d[te[1]]<<endl;
		while(q--){
			cin>>pp>>uu;
			if(pp>=2&&a[pp-1]>=a[pp]+1&&a[pp-1]<=uu){
				ci(1,1,n-1,pp-1,0);
			}
			if(pp<=n-1&&a[pp]>=a[pp+1]+1&&a[pp+1]>=uu){
				ci(1,1,n-1,pp,0);
			}
			if(pp>=2&&a[pp-1]<=a[pp]&&a[pp-1]>=uu+1){
				ci(1,1,n-1,pp-1,pp-1);
			}   
			if(pp<=n-1&&a[pp]<=a[pp+1]&&a[pp+1]<=uu-1){
				ci(1,1,n-1,pp,pp);
			}
			a[pp]=uu;
			cout<<d[te[1]]<<"\n";
		}
	}
	return 0; 	
}
posted @ 2026-01-26 21:12  bz02_2023f2  阅读(2)  评论(0)    收藏  举报  来源