CF293E Close Vertices 点分治+树状数组
开始zz写了一个主席树,后来发现写个树状数组就行~
#include <cstdio> #include <vector> #include <algorithm> #include <bits/stdc++.h> #define N 100005 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; int length,weight; namespace BIT { int C[N]; int lowbit(int t) { return t&(-t); } void update(int x,int v) { for(;x<N;x+=lowbit(x)) C[x]+=v; } int query(int x) { int re=0; for(;x>0;x-=lowbit(x)) re+=C[x]; return re; } }; ll answer; struct Node { int u,d1,d2; Node(int u=0,int d1=0,int d2=0):u(u),d1(d1),d2(d2){} }; vector<Node>v; bool cmp(Node a,Node b) { return a.d2<b.d2; } int n,edges,root,sn; int hd[N],to[N<<1],nex[N<<1],val[N<<1]; int size[N],mx[N],vis[N],rt[N]; void add(int u,int v,int c) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c; } void getroot(int u,int ff) { size[u]=1,mx[u]=0; for(int i=hd[u];i;i=nex[i]) if(to[i]!=ff&&!vis[to[i]]) getroot(to[i],u),size[u]+=size[to[i]],mx[u]=max(mx[u],size[to[i]]); mx[u]=max(mx[u],sn-size[u]); if(mx[u]<mx[root]) root=u; } // d1<=l d2<=w void getdis(int u,int ff,int d1,int d2) { v.push_back(Node(u,d1,d2)); for(int i=hd[u];i;i=nex[i]) if(to[i]!=ff&&!vis[to[i]]) getdis(to[i],u,d1+1,d2+val[i]); } ll calc(int u,int D1,int D2) { getdis(u,0,D1,D2); sort(v.begin(),v.end(),cmp); ll re=0; int i,j,l=0,r=(int)v.size()-1; for(i=1;i<(int)v.size();++i) BIT::update(v[i].d1+1,1); while(l<r) { if(v[l].d2+v[r].d2<=weight) { re+=(ll)BIT::query(length-v[l].d1+1); ++l,BIT::update(v[l].d1+1,-1); } else { BIT::update(v[r].d1+1,-1); --r; } } v.clear(); return re; } void solve(int u) { vis[u]=1; answer+=calc(u,0,0); for(int i=hd[u];i;i=nex[i]) if(!vis[to[i]]) answer-=calc(to[i],1,val[i]); for(int i=hd[u];i;i=nex[i]) if(!vis[to[i]]) sn=size[to[i]],root=0,getroot(to[i],u),solve(root); } int main() { int i,j; // setIO("input"); scanf("%d%d%d",&n,&length,&weight); for(i=1;i<n;++i) { int a=i+1,b,c; scanf("%d%d",&b,&c),add(a,b,c),add(b,a,c); } mx[root=0]=sn=n,getroot(1,0),solve(root); printf("%lld\n",answer); return 0; }