2024ICPC成都I题好分割Good Partitions
Problem - I - Codeforces
由于支持单点修改,我们的目标则是每次单点修改后高效求出gcd(S)因数个数。
#include<bits/stdc++.h>
using namespace std;
const int MAX_N=200005;
int a[MAX_N],n,q;//存储原始序列S0
vector<int>e[MAX_N];//e[i]包含i的所有因数
set<int>s;//所有“下降”位置的集合
int d[MAX_N];//d[factor]表示factor是当前多少个“下降”位置的因数
int calculate_answer(){if(s.empty())return n;//没有“下降”位置,所有k都合法,答案是nint min_element=*s.begin();//找到最小“下降”位置//因为所有“下降”位置的最大公因数gcd(S)一定是最小“下降”位置的因数//而我们要找的gcd(S)的因数也一定是最小“下降”位置的因数//所以我们只需要从最小“下降”位置的因数中筛选即可int count=0;for(auto factor:e[min_element])//遍历最小“下降”位置的所有因数if(d[factor]==s.size())count++;//如果其中一个因数factor是S中所有“下降”位置的因数,它就是gcd(S)的因数return count;
}
void insert_element(int i){s.insert(i);//插入新的“下降”位置i到集合Sfor(auto factor:e[i])d[factor]++;//新的“下降”位置i存储在e[i]中的所有因数对应的d[factor]值+1
}
void delete_element(int i){s.erase(i);//删除集合S中的“下降”位置ifor(auto factor:e[i])d[factor]--;//删除的“下降”位置i存储在e[i]中的所有因数对应的d[factor]值-1
}
void solve(){cin>>n>>q;fill(d+1,d+n+1,0);s.clear();//清空(预处理)for(int i=1;i<=n;i++){cin>>a[i];if(i>1&&a[i-1]>a[i])insert_element(i-1);}cout<<calculate_answer()<<endl;while(q--){int p,v;cin>>p>>v;//删除可能受影响的“下降”位置if(p>1&&a[p-1]>a[p])delete_element(p-1);if(p<n&&a[p]>a[p+1])delete_element(p);a[p]=v;//修改//插入可能新产生的“下降”位置if(p>1&&a[p-1]>a[p])insert_element(p-1);if(p<n&&a[p]>a[p+1])insert_element(p);cout<<calculate_answer()<<endl;}
}
signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int t;cin>>t;for(int i=1;i<MAX_N;i++)for(int j=i;j<MAX_N;j+=i)e[j].push_back(i);//埃氏筛法思想,e[j]中包含了j的所有因子while(t--)solve();return 0;
}