Description
Solution
第一眼dsu on tree然后开一个桶,然后我写了主席树
结果这是最简单的题,直接每个点记录包含的最小、最大,和size比较一下就知道了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int N=200005;
const int E=200005;
struct edge {int y,next;} e[E];
struct treeNode {int l,r,sum;} t[N*51];
int root[N],pos[N],size[N],tot;
int ls[N],ans,edCnt;
int l[N],r[N],d[N],n;
bool v[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void add_edge(int x,int y) {
d[y]++;
e[++edCnt]=(edge) {y,ls[x]}; ls[x]=edCnt;
}
void modify(int pre,int &now,int tl,int tr,int x) {
t[now=++tot]=t[pre]; t[now].sum++;
if (tl==tr) return ;
int mid=(tl+tr)>>1;
if (x<=mid) modify(t[pre].l,t[now].l,tl,mid,x);
else modify(t[pre].r,t[now].r,mid+1,tr,x);
}
int query(int pre,int now,int tl,int tr,int l,int r) {
if (tl==l&&tr==r) return t[now].sum-t[pre].sum;
int mid=(tl+tr)>>1;
if (r<=mid) return query(t[pre].l,t[now].l,tl,mid,l,r);
if (l>mid) return query(t[pre].r,t[now].r,mid+1,tr,l,r);
return query(t[pre].l,t[now].l,tl,mid,l,mid)+query(t[pre].r,t[now].r,mid+1,tr,mid+1,r);
}
void dfs1(int now) {
l[now]=r[now]=now; pos[now]=++pos[0];
modify(root[pos[0]-1],root[pos[0]],1,n,now);
size[now]=1;
for (int i=ls[now];i;i=e[i].next) {
dfs1(e[i].y);
l[now]=std:: min(l[e[i].y],l[now]);
r[now]=std:: max(r[e[i].y],r[now]);
size[now]+=size[e[i].y];
}
}
void dfs2(int now) {
for (int i=ls[now];i;i=e[i].next) {
dfs2(e[i].y);
}
if (query(root[pos[now]-1],root[pos[now]+size[now]-1],1,n,l[now],r[now])==r[now]-l[now]+1) {
v[now]=1; ans++;
}
}
int main(void) {
n=read(); int rt;
rep(i,2,n) {
int x=read(),y=read();
add_edge(x,y);
}
rep(i,1,n) if (!d[i]) rt=i;
dfs1(rt);
dfs2(rt);
printf("%d\n", ans);
return 0;
}