CF1844G Tree Weights
CF1844G Tree Weights
神仙题。
思路
设 \(x_i\) 为 \(dis(1,i)\),有关于 \(d_i\) 的等式 \(d_i=x_i+x_{i+1}-2\times x_{lca(i,i+1)}\)。
移项得到,\(x_{i+1}=d_i-x_{i}+2\times x_{lca(i,i+1)}\)。
注意力惊人,发现等式右边带一个 \(2\)。
于是 \(x_{i+1} \equiv d_i-x_{i} \mod 2\)。
这样我们求出了 \(x_{i+1}\) 的最低位。
能不能通过类似递推的方式求出 \(x_i\) 的高位以此复原 \(x_i\) 呢?
基于一个数第 \(k\) 位的结果只与小于等于 \(k\) 的位有关。
注意到 \(2\times x_{lca(i,i+1)}\),相当于每次可以用 \(x_{lca(i,i+1)}\) 的 \(k-1\) 位的结果求 \(x_{i+1}\) 第 \(k\) 位的结果,而等式中其他项都存在第 \(k\) 位,于是便可以求出 \(x_{i+1}\) 第 \(k\) 位的结果(顺序递推,\(x_i\) 的第 \(k\) 位已经求出)。
特判 \(x_i\) 小于等于父亲,以及无法复原 \(d\) 的情况。
CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+5;
int n,cok;
int LCA[maxn],st[maxn][20],dfn[maxn],u[maxn],v[maxn];
ll mod=2;
ll d[maxn],x[maxn],tmp[maxn];
vector<int>E[maxn];
inline void dfs(int u,int f)
{
dfn[u]=++cok;st[cok][0]=f;
for(auto v:E[u])
{
if(v==f) continue;
dfs(v,u);
}
}
inline int Min(int u,int v){return dfn[u]<dfn[v]?u:v;}
inline void init()
{
for(int i=1;i<=20;i++) for(int j=1;j<=(n-(1<<i)+1);j++)
st[j][i]=Min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
inline int Lca(int u,int v)
{
if(u==v) return u;
if(dfn[u]>dfn[v]) swap(u,v);
int l=dfn[u]+1,r=dfn[v],k=log2(r-l+1);
return Min(st[l][k],st[r-(1<<k)+1][k]);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
scanf("%d%d",&u[i],&v[i]);
E[u[i]].emplace_back(v[i]),E[v[i]].emplace_back(u[i]);
}
dfs(1,0);
init();
for(int i=1;i<n;i++) LCA[i]=Lca(i,i+1);
for(int i=1;i<n;i++) scanf("%lld",&d[i]);
for(mod=2;mod<=(1ll<<60);mod<<=1)
{
for(int i=1;i<=n;i++) tmp[i]=x[i];
for(int i=1;i<n;i++) x[i+1]=(d[i]%mod+2*tmp[LCA[i]]%mod-x[i]+mod)%mod;
}
for(int i=2;i<=n;i++) if(x[st[dfn[i]][0]]>=x[i]) {puts("-1");return 0;}
for(int i=1;i<n;i++)
{
if(d[i]!=x[i]+x[i+1]-2*x[LCA[i]]) {puts("-1");return 0;}
}
for(int i=1;i<n;i++)
{
if(dfn[u[i]]>dfn[v[i]]) swap(u[i],v[i]);
printf("%lld\n",x[v[i]]-x[u[i]]);
}
}

浙公网安备 33010602011771号