【2019省选模拟】—树(并查集+容斥)
先不考虑修改
考虑直接不好求,改成求不为1的个数
容斥一下就是一个质数时联通的点对个数-2个质数的积时联通的点的个数+3个质数积联通的点的个数……
发现实际上就是
联通的点的个数实际上很好求,用并查集维护一下,的时候加一个的积就可以了
但每次不能直接重置,用一个指针维护一下回收被修改的和,并查集也只能按秩合并
考虑有了修改怎么做
因为修改的次数很少
可以先不加入被修改的满足的边,记录一下
然后每次暴力枚举修改的边加入
统计答案就是了
复杂度
实际上可以记录每个数最小的质因子直接优化成
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
return res*f;
}
const int N=100005,M=1000005;
int pr[M],mu[M],vis[M],tot;
inline void init(){
mu[1]=1;
for(int i=2;i<=M-5;i++){
if(!vis[i])pr[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&i*pr[j]<=M-5;j++){
vis[i*pr[j]]=1;
if(i%pr[j]==0)break;
mu[i*pr[j]]=-mu[i];
}
}
memset(vis,0,sizeof(vis));
}
vector<int> add[M];
ll res,ans[N];
int fa[N],siz[N],*stk[N<<1],pre[M],top,u[N],v[N],w[N],x[N],y[N],e[N],chan[N],now[N],n,m,q;
inline int find(int x){
return fa[x]==x?x:find(fa[x]);
}
inline void merge(int u,int v){
int f1=find(u),f2=find(v);
if(siz[f1]<siz[f2])swap(f1,f2);
stk[++top]=&siz[f1],pre[top]=siz[f1];
res+=1ll*siz[f1]*siz[f2],siz[f1]+=siz[f2];
stk[++top]=&fa[f2],pre[top]=fa[f2];
fa[f2]=f1;
}
int main(){
n=read();init();
for(int i=1;i<n;i++)
u[i]=read(),v[i]=read(),w[i]=read();
q=read();
for(int i=1;i<=q;i++){
x[i]=e[i]=read(),y[i]=read(),chan[e[i]]=1;
}
for(int i=1;i<n;i++){
for(int j=1;j*j<=w[i];j++){
if(w[i]%j!=0)continue;
if(mu[j]){
if(chan[i])vis[j]=1;
else add[j].pb(i);
}
if(j*j!=w[i]&&mu[w[i]/j]){
if(chan[i])vis[w[i]/j]=1;
else add[w[i]/j].pb(i);
}
}
}
for(int i=1;i<=q;i++){
for(int j=1;j*j<=y[i];j++){
if(y[i]%j==0)vis[j]=vis[y[i]/j]=1;
}
}
for(int i=1;i<=n;i++)siz[i]=1,fa[i]=i;
sort(e+1,e+q+1),m=unique(e+1,e+q+1)-e-1;
for(int i=1;i<=1e6;i++){//cout<<i<<'\n';
if(!mu[i])continue;res=0;
for(int j=0;j<add[i].size();j++)
merge(u[add[i][j]],v[add[i][j]]);
int lst=top,p=res;
for(int j=0;j<=q;j++){
if(vis[i]){
for(int k=1;k<=q;k++)now[x[k]]=w[x[k]];
for(int k=1;k<=j;k++)now[x[k]]=y[k];
for(int k=1;k<=m;k++){
if(now[e[k]]%i==0)merge(u[e[k]],v[e[k]]);
}
}
ans[j]+=mu[i]*res,res=p;
while(top>lst)*stk[top]=pre[top],top--;
}
while(top)*stk[top]=pre[top],top--;
}
for(int i=0;i<=q;i++)cout<<ans[i]<<'\n';
}