这玩意其实并没有那么广义,就像“分治”或“线段树上二分”,这玩意其实是用于解决 “图中的边在一个时间区间内生效” 类的问题的。

就是用开在时间上的线段树维护边,把边挂在它覆盖的区间上,最后遍历线段树,进一个树上的点就把上面的边全暴力连上,出去的时候再全断开,一般来说常常和可撤销并查集一起用 (至少本人见过的都是),用于维护连通性或特定的大小或图符合什么奇奇怪怪的性质。

例:nfls

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define gtc() getchar()
#define fp(i,l,r) for(int i=l;i<=r;i++)
#define fb(i,l,r) for(int i=l;i>=r;i--)
#define pil pair<int,long long>
template <class T>
inline void read(T &s){
T neg=1,ch=gtc();s=0;
while(!isdigit(ch)){if(ch=='-')neg=-1;ch=gtc();}
while(isdigit(ch)){s=(s<<3)+(s<<1)+(ch-'0');ch=gtc();}
s=s*neg;
}
const ll N=1000050;
ll n,m,k,top,ans,stk[N];
struct node{
ll p,v;
};
struct edge{
ll u,v,w;
}e[N];
vector<int> nd[N],rb[N];
struct DSU{
ll fa[N],sz[N];
ll find(ll x){return fa[x]==x?x:find(fa[x]);}
ll init(){fp(i,1,1000000)fa[i]=i,sz[i]=1;}
void merge(ll x,ll y,ll ad){
ll fx=find(x),fy=find(y);
if(fx==fy)return ;
if(sz[fx]<sz[fy])swap(fx,fy);
//cout<<"mer"<<ad<<" "<<fx<<" "<<sz[fx]<<" "<<fy<<" "<<sz[fy]<<endl;
stk[++top]=fy;
if(ad)ans+=sz[fx]*sz[fy];
fa[fy]=fx;
sz[fx]+=sz[fy];
}
}dsu;
void add(ll x,ll l,ll r,ll tl,ll tr,ll v){
if(l>=tl&&r<=tr){
nd[x].emplace_back(v);
return ;
}
ll nxt=x<<1,mid=(l+r)>>1;
if(tl<=mid)add(nxt,l,mid,tl,tr,v);
if(tr>mid)add(nxt+1,mid+1,r,tl,tr,v);
}
void dfs(ll x,ll l,ll r){//cout<<"x "<<l<<" "<<r<<endl;
ll now=top;
for(auto i:nd[x]){/*cout<<i<<endl;*/dsu.merge(e[i].u,e[i].v,0);}
if(l==r){
for(auto i:rb[l]){/*cout<<i<<endl;*/dsu.merge(e[i].u,e[i].v,1);}
}
else{
ll nxt=x<<1,mid=(l+r)>>1;
dfs(nxt,l,mid);
dfs(nxt+1,mid+1,r);
}
while(top>now)dsu.sz[dsu.fa[stk[top]]]-=dsu.sz[stk[top]],dsu.fa[stk[top]]=stk[top],top--;
nd[x].clear();
}
ll sol(ll len){
ans=0;
fp(i,1,n-1)if(e[i].w+1<=n)add(1,1,n,e[i].w+1,min(n,e[i].w+len),i);//,cout<<i<<" "<<e[i].w+1<<" "<<e[i].w+len<<endl;
fp(i,1,200000)dsu.fa[i]=i,dsu.sz[i]=1;
dfs(1,1,n);
return ans;
}
int main(){
freopen("minmax.in","r",stdin);
freopen("minmax.out","w",stdout);
read(n),read(k);
fp(i,1,n-1){
read(e[i].u),read(e[i].v),read(e[i].w);
rb[e[i].w].emplace_back(i);
}
printf("%lld",sol(k)-sol(k-1));
return 0;
}

时间复杂度O(nlognlogk)O(nlognlogk)