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 ...
随机推荐
- String[] a = new String[]{"1","2"},我如果想增加一个"3"到a中,如何增加?
在java中数组是定长的,当你声明了数组的大小后数组的长度就不能改变在你的程序中,数组的初始化大小为2,a[0]="1";a[1]="2",所以无法产生元素a[ ...
- cache buffers
buffers缓冲,可以型象的理解为漏斗.如果有大量的数据要写入磁盘,由于数据量很大,磁盘不能一下子接收,所以这个时候,就有了buffer这个漏斗,先把数据放入这个漏斗里面,然后让它慢慢的注入磁盘,这 ...
- web.config详解 -- asp.net夜话之十一
1.配置文件节点说明 1.1 <appSettings>节点 1.2 <connectionStrings>节点 1.3 <compilation> ...
- 关于v$datafile中system表空间的status值始终为system
http://docs.oracle.com/cd/B19306_01/server.102/b14237/dynviews_1076.htm#REFRN30050 http://blog.itpub ...
- HTML5学习之WebWork多线程处理(八)
多线程技术在服务端技术中已经发展的很成熟了,而在Web端的应用中却一直是鸡肋 在新的标准中,提供的新的WebWork API,让前端的异步工作变得异常简单. 使用:创建一个Worker对象,指向一个j ...
- Pyqt 获取windows系统中已安装软件列表
开始之前的基础知识 1. 获取软件列表 在Python的标准库中,_winreg可以操作Windows的注册表.获取已经安装的软件列表一般是读去windows的注册表: SOFTWARE\Micros ...
- python中的monkey-patching
这个技巧我很少用过. 但知道无防. 在运行时改变函数或类的行为, 一般用猴子补丁,原类,装饰器都可以实现. #!/usr/bin/env python # -*- coding: utf-8 -*- ...
- Linux环境下stl库使用(vector)
step1: #include <iostream> #include <vector> #include <string> using namespace std ...
- WPF程序最小化到任务通知栏
我们通常使用的桌面软件,都可以最小化到任务通知栏,并且可以从任务通知栏再打开当前软件,或者通过软件的快捷方式从任务通知栏呼出. 我们可以通过下面的方式把WPF程序最小化到任务栏.由于WPF并没有实现N ...
- 跟着鸟哥学Linux系列笔记3-第11章BASH学习
跟着鸟哥学Linux系列笔记0-扫盲之概念 跟着鸟哥学Linux系列笔记0-如何解决问题 跟着鸟哥学Linux系列笔记1 跟着鸟哥学Linux系列笔记2-第10章VIM学习 认识与学习bash 1. ...