10/27 Contest 5
A:小分讨+dp
C:发现是所有的数和它的倍数有限制,对于值域 \(n\) 这样的限制也只有 \(\sum\limits_{i=1}^n\frac{n}{i}=n\log n\) 个,考虑如何表示这些限制。
考虑对于限制 u,v,若两点都不是对方的祖先,那么就不能有 u 子树中的点和 v 子树中的点相连;若 u 是 v 的祖先,那么设 w 为 u 的一个儿子,同时也是 v 的祖先,那么所有不在 w 子树中的点不能和在 v 子树中的点相连。我们发现这些性质在 dfn 序上都是一段连续的区间,想到在 dfn 上扫描线;例如不是祖先就是两个区间内中的点不能互联,是祖先就是一个前缀和一个后缀不能和一个区间相连;扫描线直接做即可。
code:
#include <bits/stdc++.h>
using namespace std;
// #define int long long
#define LL long long
#define ULL unsigned long long
#define DB double
#define LD long double
// #define SZ(x) (int)(x.size())
#define PII pair<int,int>
#define PLL pair<long long,long long>
#define fr first
#define sc second
#define popcnt __builtin_popcount
#define inv(x) ksm(x,P-2)
// #define mp make_pair
const int N=1e5+10,K=510;
const LL P=998244353;
int n,a[N],p[N];
vector<int> g[N];
struct mod {int l,r,v;
};
vector<mod> q[N];
int fa[N][25], dep[N],dfn[N],dfncnt=0,siz[N];
void dfs(int u, int f, int d) {fa[u][0] = f;dep[u] = d;dfn[u]=++dfncnt;siz[u]=1;for(auto it : g[u]) {if(it != f) {dfs(it, u, d + 1);siz[u]+=siz[it];}}
}
int LCA(int u, int v) {if(dep[u] < dep[v]) swap(u, v);for(int i = 20; i >= 0; i--) {if(dep[fa[u][i]] >= dep[v]+1) u = fa[u][i];}if(fa[u][0] == v) return u;if (dep[u]>dep[v]) u=fa[u][0];for(int i = 20; i >= 0; i--) {if(fa[u][i] != fa[v][i]) {u = fa[u][i];v = fa[v][i];}}return u;
}
void Add(int u,int l,int r,int v) {q[u].push_back({l,r,v});
}
struct SEG {int t[N<<2],s[N<<2];void push_up(int u,int l,int r) {int ls=u<<1,rs=u<<1|1;if (l==r) s[u]=(t[u]>0);else if (t[u]) s[u]=r-l+1;else s[u]=s[ls]+s[rs];}void add(int u,int l,int r,int x,int y,int k) {if (l>y||r<x) return;if (l>=x&&r<=y) {t[u]+=k; push_up(u,l,r); return;}int mid=(l+r)>>1,ls=u<<1,rs=u<<1|1;add(ls,l,mid,x,y,k); add(rs,mid+1,r,x,y,k);push_up(u,l,r);}
} tr;
int work() {cin >> n;for(int i=1;i<=n;i++) cin>>a[i],p[a[i]]=i;for(int i=1,u,v;i<n;i++) {cin>>u>>v; g[u].push_back(v); g[v].push_back(u);}dfs(1, 0, 1);for(int j = 1; j <= 20; j++) {for(int i = 1; i <= n; i++) {fa[i][j] = fa[fa[i][j - 1]][j - 1];}}for(int i=1;i<=n;i++) {for(int j=i+i;j<=n;j+=i) {int u=p[i],v=p[j];int lca=LCA(u,v);if (dep[u]>dep[v]) swap(u,v);if (fa[lca][0]==u) {Add(dfn[v],1,dfn[lca]-1,1);Add(dfn[v]+siz[v],1,dfn[lca]-1,-1);Add(dfn[v],dfn[lca]+siz[lca],n,1);Add(dfn[v]+siz[v],dfn[lca]+siz[lca],n,-1);Add(1,dfn[v],dfn[v]+siz[v]-1,1);Add(dfn[lca],dfn[v],dfn[v]+siz[v]-1,-1);Add(dfn[lca]+siz[lca],dfn[v],dfn[v]+siz[v]-1,1);Add(n+1,dfn[v],dfn[v]+siz[v]-1,-1);} else {Add(dfn[u],dfn[v],dfn[v]+siz[v]-1,1);Add(dfn[u]+siz[u],dfn[v],dfn[v]+siz[v]-1,-1);Add(dfn[v],dfn[u],dfn[u]+siz[u]-1,1);Add(dfn[v]+siz[v],dfn[u],dfn[u]+siz[u]-1,-1);}}}LL ans=0;// int mxx=2e9;for (int i=1;i<=n;i++) {for (auto it:q[i]) {// mxx=min(mxx,it.r-it.l);tr.add(1,1,n,it.l,it.r,it.v);}ans+=n-tr.s[1];}// cout<<" "<<mxx<<'\n';cout<<ans;return 0;
}
signed main() {ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);// init();// freopen("test.in", "r", stdin);// freopen("test.out", "w", stdout);int T=1;// cin>>T;while (T--) { work(); }return 0;
}