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 ...
随机推荐
- python中random模块使用
- Python 文件处理
文件夹: 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 返回指定目录下的所有文件和目录名:os.listdir() 函数用来删除一个文件:os.remove() 删 ...
- Nginx反向代理设置 从80端口转向其他端口
[root@localhost bin]# netstat -lnutp Active Internet connections (only servers) Proto Recv-Q Send-Q ...
- Android 5.0 如何正确启用isLoggable(一)__使用详解
转自:http://blog.csdn.net/yihongyuelan/article/details/46409389 isLoggable是什么 在Android源码中,我们经常可以看到如下代码 ...
- 【转载】 Python 调整屏幕分辨率
转载来自: http://www.cnblogs.com/fatterbetter/p/4115423.html 需要用windows的api,ChangeDisplaySettings 实现代码如下 ...
- tornado使用(Mac)
安装需求 Tornado 在 Python 2.5, 2.6, 2.7 中都经过了测试.要使用 Tornado 的所有功能,你需要安装 PycURL (7.18.2 或更高版本) 以及 simplej ...
- PHP日期操作类代码-农历-阳历转换、闰年、计算天数等
<?php class Lunar { var $MIN_YEAR = 1891; var $MAX_YEAR = 2100; var $lunarInfo = array( array(0,2 ...
- 银行管理系统[C++]
//项目:银行管理系统 //系统实现的主要有管理,取款机管理,用户查询等功能: //*管理模块:存款.取款.开户.销户.修改信息.办卡.挂失卡; //*用户查询模块; //*取款机信息管理模块:管理员 ...
- 在Salesforce中处理Email的发送
在Salesforce中可以用自带的 Messaging 的 sendEmail 方法去处理Email的发送 请看如下一段简单代码: public boolean TextFormat {get;se ...
- HDU 1540 Tunnel Warfare 平衡树 / 线段树:单点更新,区间合并
Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Lim ...