我是题目传送门呀
题目是点分治的模板题,然而我不会点分治,数据是10000,LCA枚举一下复杂度是(n2logn),掐指一算(python算的 ),复杂度不是刚刚好吗?就想着写一个LCA莽一下,本来以为不会TLE的,然而只有60分。
既然代码没有AC,那我就写一篇博客吧
LCA求点对距离很简单,对于点对(u,v),其距离就是dis[u]+dis[v]-2*dis[lca(u,v)],这个很简单吧,大家很容易想明白的。
dis就是根到结点的距离啦。
然后我dfs直接从1开始,我就默认他是根节点啦,其实哪个点是根节点对于点对的距离是没有影响的。
下面还是放代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int fa[maxn][21];
int lg[maxn];
int depth[maxn];
int vis[maxn];
int dis[maxn];
int n,m;
struct node
{
int to;
int cost;
};
vector<node>G[maxn];
void dfs(int now,int last)
{
vis[now] = 1;
depth[now] = depth[last]+1;
fa[now][0] = last;
for(int i=1;(1<<i)<=depth[now];i++)
{
fa[now][i] = fa[fa[now][i-1]][i-1];
}
for(int i=0;i<G[now].size();i++)
{
if(G[now][i].to!=last)
{
dis[G[now][i].to] = dis[now]+G[now][i].cost;
dfs(G[now][i].to,now);
}
}
}
int lca(int x,int y)
{
if(depth[x]>depth[y]) swap(x,y);
while(depth[x]!=depth[y])
{
y = fa[y][lg[depth[y]-depth[x]]-1];
}
if(x==y) return x;
for(int i=lg[depth[x]]-1;i>=0;i--)
{
if(fa[x][i]!=fa[y][i])
{
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][0];
}
int query(int k)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j) continue;
if(dis[i]+dis[j]-2*dis[lca(i,j)]==k) return true;
}
}
return false;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n-1;i++)
{
int x,y,z;
cin>>x>>y>>z;
G[x].push_back({y,z});
}
for(int i=1;i<=n;i++)
{
lg[i] = lg[i-1]+(1<<lg[i-1]==i);
}
dfs(1,0);
int k;
for(int i=0;i<m;i++)
{
cin>>k;
if(query(k)) cout<<"AYE"<<endl;
else cout<<"NAY"<<endl;
}
return 0;
}
第一次用MarkDown,试试啥效果。
为什么代码没高亮啊
然后我点分治也T了四个点,也只有60分qwq
奥奥,点分治写炸了,下面放上100分的点分治吧!
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int n,m;
int sum,rt;
int sz[maxn];
struct node
{
int to;
int cost;
};
vector<node> G[maxn];
int mxf[maxn],vis[maxn];
int dis[maxn],ans[10000010];
int cnt;
void getrt(int now,int last)
{
sz[now] = 1;
mxf[now] = 0;
for(int i=0;i<G[now].size();i++)
{
int v = G[now][i].to;
if(v==last || vis[v]) continue;
getrt(v,now);
sz[now] += sz[v];
mxf[now] = max(mxf[now],sz[v]);
}
mxf[now] = max(mxf[now],sum-sz[now]);
if(mxf[now]<mxf[rt]) rt = now;
}
void getdis(int now,int last,int len)
{
dis[++cnt] = len;
for(int i=0;i<G[now].size();i++)
{
int v = G[now][i].to;
if(vis[v] || v==last) continue;
getdis(v,now,len+G[now][i].cost);
}
}
void solve(int now,int len,int w)
{
cnt = 0;
getdis(now,0,len);
for(int i=1;i<=cnt;i++)
{
for(int j=1;j<=cnt;j++)
{
if(i!=j) ans[dis[i]+dis[j]] += w;
}
}
}
void divide(int x)
{
solve(x,0,1);
vis[x] = 1;
for(int i=0;i<G[x].size();i++)
{
int v = G[x][i].to;
if(vis[v]) continue;
solve(v,G[x][i].cost,-1);
sum = sz[x];
rt = 0;
mxf[0] = n;
getrt(v,x);
divide(rt);
}
}
int main()
{
scanf("%d%d",&n,&m);
int x,y,z;
for(int i=0;i<n-1;i++)
{
scanf("%d%d%d",&x,&y,&z);
G[x].push_back({y,z});
G[y].push_back({x,z});
}
sum = mxf[0] = n;
rt = 0;
getrt(1,0);
divide(rt);
int k;
for(int i=0;i<m;i++)
{
scanf("%d",&k);
if(ans[k]) printf("AYE\n");
else printf("NAY\n");
}
return 0;
}
淀粉质真好吃qwq