ReTF @ 2023-10-16 10:50:27
如题,我用的是
从第
程序是能跑出来的,但是跑的特别慢。
求助大佬我的启发式合并是不是写假了。
#include"bits/stdc++.h"
using namespace std;
#pragma GCC optimize(2)
#define endl '\n'
const int maxn = 3e5+10;
const int lgn = 18;
int n,m,f[maxn][lgn+2],dep[maxn],ans[maxn];
int t[maxn];
multiset<int>s[3][maxn];
vector<int>e[maxn];
int to[3][maxn],dl[3][maxn];
vector<int>add[3][maxn],del[3][maxn];
int delta[3]={1,-1,0};
#define mi multiset<int>::iterator
int cnt;
void dsu(int id,int U,int V){
//把 u 合并到 v 上
int &u=to[id][U],&v=to[id][V];
if(u==v)return;
if(s[id][u].size()>s[id][v].size())swap(u,v),swap(U,V);
for(mi it=s[id][u].begin();it!=s[id][u].end();it++)
s[id][v].insert((*it)+dl[id][u]-dl[id][v]);
u=v;
}
void dfs(int p,int Fa){
dep[p]=dep[Fa]+1;
for(int i=0;i<e[p].size();i++){
int to=e[p][i];
if(to==Fa)continue;
dfs(to,p);
f[to][0]=p;
}
}
int Lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
for(int i=lgn;i>=0;i--)
if(dep[f[u][i]]>=dep[v])
u=f[u][i];
if(u==v)return u;
for(int i=lgn;i>=0;i--)
if(f[u][i]!=f[v][i])
u=f[u][i],v=f[v][i];
return f[u][0];
}
void query(int id,int p,int Fa){
for(int i=0;i<e[p].size();i++){
int to=e[p][i];
if(to==Fa)continue;
query(id,to,p);
dsu(id,to,p);
}
int pos=to[id][p];
dl[id][pos]+=delta[id];
for(int j=0;j<add[id][p].size();j++){
int to=add[id][p][j]-dl[id][pos];
s[id][pos].insert(to);
}
for(int j=0;j<del[id][p].size();j++){
int to=del[id][p][j]-dl[id][pos];
if(s[id][pos].find(to)!=s[id][pos].end())
s[id][pos].erase(s[id][pos].find(to));
}
ans[p]+=s[id][pos].count(t[p]-dl[id][pos]);
}
int main(){
//freopen("P1600_9.in","r",stdin);
//freopen("ReTF.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1,u,v;i<n;i++){
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,0);
for(int j=1;j<=lgn;j++)
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
for(int i=1;i<=n;i++)
cin>>t[i],to[0][i]=to[1][i]=i;
for(int i=1,u,v;i<=m;i++){
cin>>u>>v;
int Lc=Lca(u,v),dis=dep[u]+dep[v]-dep[Lc]*2;
add[0][u].push_back(0);
if(Lc!=1)del[0][f[Lc][0]].push_back(dep[u]-dep[Lc]+1);
add[1][v].push_back(dis);
del[1][Lc].push_back(dep[u]-dep[Lc]);
}
query(0,1,0);
query(1,1,0);
for(int i=1;i<=n;i++)
cout<<ans[i]<<' ';
}
by cmach_socket @ 2024-02-24 10:35:08
我的树链剖分TLE#20 跑了9s
同为大常数选手