P7880
P7880
考虑一个点在什么时候会被选作 lca。将其子树内的所有点列出来,表示为
分析一下这样的点对的个数,发现我们可以使用启发式合并来合并子树信息,于是点对数量是
求出所有点对后,我们将其按对应点的颜色分类。对于一种颜色,如果点
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,qq[500003][2],ans[500003],dep[200003],col[200003],F[200003];
int stk[500003],tot;
map<int,int>mp;
set<int>R[200003];
int totr,ys[200003],sz[200003];
struct Que{
int v1;
int v2;
int v3;
}Q[4000003];
int totQ;
int k1,k2,k3,k4,k5,k6,k7,k8,k9;
vector<pair<int,int> >E[200003];
vector<pair<int,int> >lst[200003];
void dfs(int now){
for(auto i:E[now]){
if(i.first==F[now])continue;
F[i.first]=now;
dep[i.first]=dep[now]+i.second;
dfs(i.first);
}
return;
}
void Merge(int X,int Y,int mk){
auto p=R[X].begin();
for(auto i:R[Y]){
p=R[X].lower_bound(i);
if(p!=R[X].end()&&(*p)>i)lst[mk].emplace_back(make_pair(i,(*p)));
if(p==R[X].begin())continue;
p--;
if(p!=R[X].end()&&(*p)<i)lst[mk].emplace_back(make_pair((*p),i));
}
for(auto i:R[Y])R[X].insert(i);
R[Y].clear();
sz[X]+=sz[Y];
sz[Y]=0;
return;
}
void dfs2(int now){
lst[col[now]].emplace_back(make_pair(now,now));
ys[now]=++totr;
R[totr].insert(now);
sz[totr]=1;
for(auto i:E[now]){
if(i.first==F[now])continue;
dfs2(i.first);
if(sz[ys[now]]<sz[ys[i.first]])swap(ys[now],ys[i.first]);
Merge(ys[now],ys[i.first],col[now]);
}
return;
}
vector<int>lstq[200003];
vector<int>lstop[200003];
int TreeAr[200003];
int lowbit(int X){return (X&(-X));}
void add(int l,int r){
for(int i=l;i<=n+10;i+=lowbit(i))TreeAr[i]++;
for(int i=r+1;i<=n+10;i+=lowbit(i))TreeAr[i]--;
return;
}
int Query(int wz){
int ret=0;
for(int i=wz;i;i-=lowbit(i))ret+=TreeAr[i];
return ret;
}
int read(){
int xx=0,ff=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')ff=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')xx=xx*10+ch-'0',ch=getchar();
return xx*ff;
}
void write(int xx){
if(xx<0)putchar('-'),xx=-xx;
if(xx>9)write(xx/10);
putchar(xx%10+'0');
return;
}
signed main(){
n=read();
m=read();
for(int i=1;i<n;i++){
k1=read();
k2=read();
k3=read();
E[k1].emplace_back(make_pair(k2,k3));
E[k2].emplace_back(make_pair(k1,k3));
}
for(int i=1;i<=m;i++){
qq[i][0]=read();
qq[i][1]=read();
}
dfs(1);
for(int i=1;i<=n;i++){
if(mp[dep[i]]==0){
stk[++tot]=dep[i];
mp[dep[i]]=1;
}
}
sort(stk+1,stk+tot+1);
for(int i=1;i<=tot;i++)mp[stk[i]]=i;
for(int i=1;i<=n;i++)col[i]=mp[dep[i]];
dfs2(1);
for(int i=1;i<=tot;i++){
sort(lst[i].begin(),lst[i].end());
k7=n+10;
for(int j=(int)(lst[i].size())-1;j>=0;j--){
if(k7<=lst[i][j].second)continue;
Q[++totQ].v1=lst[i][j].first;
Q[totQ].v2=lst[i][j].second;
Q[totQ].v3=k7-1;
k7=lst[i][j].second;
}
}
for(int i=1;i<=totQ;i++)lstop[Q[i].v1].emplace_back(i);
for(int i=1;i<=m;i++)lstq[qq[i][0]].emplace_back(i);
for(int i=n;i;i--){
for(auto j:lstop[i])add(Q[j].v2,Q[j].v3);
for(auto j:lstq[i])ans[j]=Query(qq[j][1]);
}
for(int i=1;i<=m;i++){
write(ans[i]);
putchar('\n');
}
return 0;
}