先树链剖分,一棵子树的编号在数组上连续,一条链用树链剖分,把这些线段全部取出来,做差分,找到有多少点被>=t条线段覆盖即可。
#include#include #include #include #include #define ll long long using namespace std;const int maxn=10000010;struct poi{ int too,pre;}e[maxn<<1];int n,m,x,y,z,tot,cnt,ans,a,b,t,cntt;int last[maxn],size[maxn],fa[maxn],dep[maxn],son[maxn],w[maxn],top[maxn],mx[maxn],q[maxn],s[maxn];inline void read(int &k){ int f=1;k=0;char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar(); k*=f;}inline void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}inline void update(int x,int y){q[++cntt]=x;q[++cntt]=y+1;s[x]++;s[y+1]--;}void dfs1(int x){ size[x]=1; for(int i=last[x];i;i=e[i].pre) { int too=e[i].too; if(too==fa[x])continue; fa[too]=x; dep[too]=dep[x]+1; dfs1(too); if(size[too]>size[son[x]])son[x]=too; size[x]+=size[too]; }}void dfs2(int x,int tp){ mx[x]=w[x]=++cnt;top[x]=tp; if(son[x])dfs2(son[x],tp),mx[x]=max(mx[x],mx[son[x]]); for(int i=last[x];i;i=e[i].pre) if(e[i].too!=son[x]&&e[i].too!=fa[x]) dfs2(e[i].too,e[i].too),mx[x]=max(mx[x],mx[e[i].too]);}inline void work(int x,int y){ int f1=top[x],f2=top[y]; while(f1!=f2) { if(dep[f1] =t)ans+=q[i+1]-q[i]; } for(int i=1;i<=cntt;i++)s[q[i]]=0; printf("%d\n",ans); } return 0;}