HDU5331 : Simple Problem
因为是二分图,所以最大独立集$=$总点数$-$最大匹配。
因为是树,所以具有贪心性质,设$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的更多相关文章
- BZOJ 4679/Hdu5331 Simple Problem LCT or 树链剖分
4679: Hdu5331 Simple Problem 题意: 考场上,看到这道题就让我想起BZOJ4712洪水.然后思路就被带着飞起了,完全没去考虑一条链的情况,于是GG. 解法:先考虑一条链的做 ...
- POJ 3468 A Simple Problem with Integers(线段树 成段增减+区间求和)
A Simple Problem with Integers [题目链接]A Simple Problem with Integers [题目类型]线段树 成段增减+区间求和 &题解: 线段树 ...
- POJ 3468 A Simple Problem with Integers(线段树/区间更新)
题目链接: 传送门 A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Description Yo ...
- poj 3468:A Simple Problem with Integers(线段树,区间修改求和)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 58269 ...
- ACM: A Simple Problem with Integers 解题报告-线段树
A Simple Problem with Integers Time Limit:5000MS Memory Limit:131072KB 64bit IO Format:%lld & %l ...
- poj3468 A Simple Problem with Integers (线段树区间最大值)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 92127 ...
- POJ3648 A Simple Problem with Integers(线段树之成段更新。入门题)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 53169 Acc ...
- 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 ...
- POJ 3468 A Simple Problem with Integers(线段树区间更新区间查询)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 92632 ...
随机推荐
- 恶趣味小游戏 I'm hungry
之前学算法的时候无聊做了个游戏放松放松,现在传到了github以免电脑坏了就永远丢失了... github地址:https://github.com/BenDanChen/IamHungry I am ...
- json数据类型
JSON 语法规则 JSON 语法是 JavaScript 对象表示法语法的子集. 数据在名称/值对中 数据由逗号分隔 花括号保存对象 方括号保存数组 JSON 名称/值对 JSON 数据的书写格式是 ...
- Delphi之DLL知识学习5---在Delphi应用程序中使用DLL
首先说明一下:同一个动态库(DLL)被多个的程序加载的话,那么将会在每次加载的时候都会重新分配新的独立的内存空间,绝对不是共用一个,所以当一个DLL被多次加载的时候,其会在内存中“复制”多份,不会互相 ...
- Bootstrap简介
接下来的一段时间,想研究一下现有的网页框架,第一个不容错过的就是Bootstrap,Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架.Bootstrap 是基于 HTML.CS ...
- c++ 读取txt文件并输出到控制台
代码如下: #include "stdafx.h" #include<iostream> #include<fstream> #include<cst ...
- pythonyCool-moviepy
你想要登上山顶去看美丽的风光,却在山腰发现了草莓. 今天给大家推荐一个很酷的python包moviepy.我在伯乐在线发现的看这个链接: http://python.jobbole.com/81185 ...
- connot resolve symbol R
出现这个原因大都是layout里的xml文件出错,就不会自动生成R文件
- java学习笔记(2):获取文件名和自定义文件过滤器
//自定义文件过滤器import java.io.File; import javax.swing.filechooser.*; public class JavaChooser extends Fi ...
- 函数调用关于从Ring3转到Ring0 ESP堆栈变化
在ring0堆栈获取ring3堆栈方式 第一种方式 [esp+4] == [esp+参数个数*4+4] 如果这里不相等就需要用第二种方式 [[esp+参数个数*4+8]] 这里面的值就是Ring3的堆 ...
- 词法分析 after Coding
学习词法分析,认为词法分析很难. 虽然不懂,但是要完成作业. 去图书馆或者看书借鉴代码,修改错误,让代码正常运行. 学习词法分析后,了解到自己有很多的不足: 1.代码不是很熟练,课本知识不了解.知识面 ...