小V和gcd树 树链剖分
好题
题意 如上
题外话:
1.树链剖分其实就是logn条链连接成,这条链满足头节点为轻儿子,之后均是重儿子相连。。。。1.轻-重-重-重-重-重-重 2.轻-重-重-重3.轻-重 这样的连在一起
2.top[x]为轻儿子 ,也是重链头
3.注意第二遍 为dfs2(1,1)
思路:
1.放入模板
2.update 更改u->son[u] 与 u->fa[u] 的权值。
3.query 时 记住top[x]为轻儿子,而轻儿子与father的权值肯定未被更改需要单独计算。但是除了top[x]都被更改过,直接暴力计算即可 其实应该主席树查询的但数据水了 。
4.st[u]表示u->fa[u]的边权,查询暴力查询即可
更新下树剖的版子
int siz[maxn],fa[maxn],deep[maxn],son[maxn],top[maxn],dfn[maxn];
void dfs1(int u,int fr){
siz[u]=1,fa[u]=fr,deep[u]=deep[fr]+1;
for(auto v:edge[u]){
if(v==fr) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int fr){
top[u]=fr;
static int cnt=0;
dfn[u]=++cnt;
if(son[u]) dfs2(son[u],fr);
for(auto v:edge[u]){
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
完整代码
#pragma GCC optimize(3,"Ofast","inline") //G++
#include<bits/stdc++.h>
#define mem(a,x) memset(a,x,sizeof(a))
#define debug(x) cout << #x << ": " << x << endl;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fcout cout<<setprecision(4)<<fixed
using namespace std;
typedef long long ll;
//======================================
namespace FastIO{
char print_f[105];void read() {}void print() {putchar('\n');}
template <typename T, typename... T2>
inline void read(T &x, T2 &... oth){x = 0;char ch = getchar();ll f = 1;while (!isdigit(ch)){if (ch == '-')f *= -1;ch = getchar();}while (isdigit(ch)){x = x * 10 + ch - 48;ch = getchar();}x *= f;read(oth...);}
template <typename T, typename... T2>
inline void print(T x, T2... oth){ll p3=-1;if(x<0) putchar('-'),x=-x;do{print_f[++p3] = x%10 + 48;}while(x/=10);while(p3>=0) putchar(print_f[p3--]);putchar(' ');print(oth...);}} // namespace FastIO
using FastIO::print;
using FastIO::read;
//======================================
typedef pair<int,int> pii;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int maxn = 1e6+5;
int a[maxn];
vector<int>edge[maxn];
void add(int x,int y){
edge[x].push_back(y);
edge[y].push_back(x);
}
int st[maxn];
int siz[maxn],fa[maxn],deep[maxn],son[maxn],top[maxn],dfn[maxn];
void dfs1(int u,int fr){
siz[u]=1,fa[u]=fr,deep[u]=deep[fr]+1;
for(auto v:edge[u]){
if(v==fr) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int fr){
top[u]=fr;
static int cnt=0;
dfn[u]=++cnt;
st[cnt]=__gcd(a[u],a[fa[u]]);
if(son[u]) dfs2(son[u],fr);
for(auto v:edge[u]){
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
int qurey2(int x,int y,int z){
int res=0;
for(int i=x;i<=y;i++) res+=st[i]<=z;
return res;
}
int qurey(int x,int y,int z){
int res=0;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
res+=qurey2(dfn[top[x]]+1,dfn[x],z);
x=top[x];
res+=__gcd(a[x],a[fa[x]])<=z;
x=fa[x];
}
if(deep[x]>deep[y]) swap(x,y);
res+=qurey2(dfn[x]+1,dfn[y],z);
return res;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("H:\\code\\in.in", "r", stdin);
freopen("H:\\code\\out.out", "w", stdout);
clock_t c1 = clock();
#endif
//**************************************
int n,_;
read(n,_);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<n;i++){
int x,y;
read(x,y);
add(x,y);
}
dfs1(1,0);
dfs2(1,1);
while(_--){
int op;
read(op);
if(op==1){
int x,y;
read(x,y);
a[x]=y;
st[dfn[x]]=__gcd(y,a[fa[x]]);
if(son[x])
st[dfn[son[x]]]=__gcd(y,a[son[x]]);
}
else{
int x,y,z;
read(x,y,z);
print(qurey(x,y,z));
}
}
//**************************************
#ifndef ONLINE_JUDGE
cerr << "Time:" << clock() - c1 << "ms" << endl;
#endif
return 0;
}