因为是二分图,所以最大独立集$=$总点数$-$最大匹配。

因为是树,所以具有贪心性质,设$f_i$表示$i$是否与其孩子匹配,$a_i$表示$i$的孩子里$f$为$0$的个数,则$f_i=[a_i>0]$。

加入一个新的叶子的时候,影响的$a$是连续的一段,这一段上与它距离为奇数的点的$a$都要是$0$,距离为偶数的点都要是$1$。

树链剖分+线段树维护即可。

时间复杂度$O(n\log^2n)$。

#include<cstdio>
const int N=100010,M=262150;
int n,i,y,f[N],g[N],nxt[N],d[N],size[N],son[N],loc[N],top[N],q[N],dfn;
int len[M],v[M],mx[M][2],tag[M][2],rev[M];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
void dfs(int x){
size[x]=1;
for(int i=g[x];i;i=nxt[i]){
d[i]=d[x]+1;
dfs(i),size[x]+=size[i];
if(size[i]>size[son[x]])son[x]=i;
}
}
void dfs2(int x,int y){
q[loc[x]=++dfn]=x;top[x]=y;
if(son[x])dfs2(son[x],y);
for(int i=g[x];i;i=nxt[i])if(i!=son[x])dfs2(i,i);
}
inline int max(int a,int b){return a>b?a:b;}
inline void tag1(int o,int x,int p){mx[x][o]+=p;tag[x][o]+=p;}
inline void rev1(int x){v[x]=len[x]-v[x];rev[x]^=1;}
inline void pb(int x){
for(int o=0;o<2;o++)if(tag[x][o])tag1(o,x<<1,tag[x][o]),tag1(o,x<<1|1,tag[x][o]),tag[x][o]=0;
if(rev[x])rev1(x<<1),rev1(x<<1|1),rev[x]=0;
}
inline void up(int x){
v[x]=v[x<<1]+v[x<<1|1];
for(int o=0;o<2;o++)mx[x][o]=max(mx[x<<1][o],mx[x<<1|1][o]);
}
void build(int x,int a,int b){
len[x]=b-a+1;v[x]=rev[x]=0;
for(int o=0;o<2;o++)mx[x][o]=tag[x][o]=0;
if(a==b)return;
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b);
}
void ask(int x,int a,int b,int c,int d,int o){
if(c<=a&&b<=d){
if(mx[x][o]<=1&&mx[x][o^1]<=0){y=a;return;}
if(a==b){if(!y)y=N;return;}
}
pb(x);
int mid=(a+b)>>1;
if(d>mid){
ask(x<<1|1,mid+1,b,c,d,o);
if(y>mid+1)return;
}
if(c<=mid)ask(x<<1,a,mid,c,d,o);
}
void change(int x,int a,int b,int c,int d,int o){
if(c<=a&&b<=d){tag1(o,x,-1);tag1(o^1,x,1);return;}
pb(x);
int mid=(a+b)>>1;
if(c<=mid)change(x<<1,a,mid,c,d,o);
if(d>mid)change(x<<1|1,mid+1,b,c,d,o);
up(x);
}
void reverse(int x,int a,int b,int c,int d){
if(c<=a&&b<=d){rev1(x);return;}
pb(x);
int mid=(a+b)>>1;
if(c<=mid)reverse(x<<1,a,mid,c,d);
if(d>mid)reverse(x<<1|1,mid+1,b,c,d);
up(x);
}
inline void modify(int x,int o){
for(;x;x=f[top[x]]){
y=0;
ask(1,1,n,loc[top[x]],loc[x],o);
if(y<N)y=q[y];
if(y==N){
change(1,1,n,loc[x],loc[x],o);
return;
}
change(1,1,n,loc[y],loc[x],o);
reverse(1,1,n,loc[y],loc[x]);
if(y!=top[x]){
y=f[y];
change(1,1,n,loc[y],loc[y],o);
return;
}
}
}
int main(){
while(~scanf("%d",&n)){
for(dfn=0,i=1;i<=n;i++)g[i]=son[i]=0;
for(i=2;i<=n;i++){
read(f[i]),f[i]++;
nxt[i]=g[f[i]],g[f[i]]=i;
}
dfs(1),dfs2(1,1),build(1,1,n);
for(i=2;i<=n;i++)modify(f[i],d[i]&1),printf("%d\n",i-v[1]);
}
return 0;
}

  

HDU5331 : Simple Problem的更多相关文章

  1. BZOJ 4679/Hdu5331 Simple Problem LCT or 树链剖分

    4679: Hdu5331 Simple Problem 题意: 考场上,看到这道题就让我想起BZOJ4712洪水.然后思路就被带着飞起了,完全没去考虑一条链的情况,于是GG. 解法:先考虑一条链的做 ...

  2. POJ 3468 A Simple Problem with Integers(线段树 成段增减+区间求和)

    A Simple Problem with Integers [题目链接]A Simple Problem with Integers [题目类型]线段树 成段增减+区间求和 &题解: 线段树 ...

  3. POJ 3468 A Simple Problem with Integers(线段树/区间更新)

    题目链接: 传送门 A Simple Problem with Integers Time Limit: 5000MS     Memory Limit: 131072K Description Yo ...

  4. poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   ...

  5. ACM: A Simple Problem with Integers 解题报告-线段树

    A Simple Problem with Integers Time Limit:5000MS Memory Limit:131072KB 64bit IO Format:%lld & %l ...

  6. poj3468 A Simple Problem with Integers (线段树区间最大值)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 92127   ...

  7. POJ3648 A Simple Problem with Integers(线段树之成段更新。入门题)

    A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 53169 Acc ...

  8. BZOJ-3212 Pku3468 A Simple Problem with Integers 裸线段树区间维护查询

    3212: Pku3468 A Simple Problem with Integers Time Limit: 1 Sec Memory Limit: 128 MB Submit: 1278 Sol ...

  9. POJ 3468 A Simple Problem with Integers(线段树区间更新区间查询)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 92632   ...

随机推荐

  1. Java bean validation 规范与参考实现

    1.Apache Bval 依赖包:validation-api-1.1.0.Final.jar org.apache.bval.bundle-1.1.1.jar bval-core-1.1.1.ja ...

  2. java1.8中Lambda表达式reduce聚合测试例子

    public class LambdaTest { public static void main(String[] args) { // 相当于foreach遍历操作结果值 Integer out ...

  3. 给UILabel设置不同的字体和颜色

    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"Using NSAt ...

  4. 一般处理程序获取session值

    1.要在一般处理程序中获取其他页面的session值,需要引用名空间: using System.Web.SessionState; 2.然后继承一个接口:IRequiresSessionState, ...

  5. MVC – 14.ajax异步请求

    14.1.配置文件 14.2.AjaxHelper – 异步链接按钮 14.3.AjaxHelper – 异步表单 AjaxOptions常见属性: 14.4.AjaxOptions对象生成[对应]触 ...

  6. SQLServer系统监控

    http://blog.sina.com.cn/s/blog_519d269c0100gx09.html http://blog.csdn.net/qxlwuyuhui0801/article/det ...

  7. 关于 redis、memcache、mongoDB 的对比(转载)

    from:http://yang.u85.us/memcache_redis_mongodb.pdf 从以下几个维度,对 redis.memcache.mongoDB 做了对比.1.性能都比较高,性能 ...

  8. Swipe to back not working滑动后退功能消失?

    如果你发现滑动后退功能突然失效了,很可能是因为你隐藏了NavigationBar 或者定制了 leftBarButtonItem(s) 这会导致 NavigationController 的 inte ...

  9. [LeetCode] Gas Station

    Recording my thought on the go might be fun when I check back later, so this kinda blog has no inten ...

  10. HDU4495 Rectangle

    求组成的等腰三角形面积最大值. 对此题的总结:暴力出奇迹 组成的三角形放置方式一共只有4种,用ans表示目前已知的最长三角形的边长,从上到下,从左到右枚举顶点,再枚举边长,一个重要剪枝是枚举边长l时先 ...