【XSY2665】没有上司的舞会 LCT DP
题目大意
有一棵树,最开始只有一个点。每次会往这棵树中加一个点,总共\(n\)次。输出每次加点后树的最大独立集大小。
强制在线。
\(n\leq 300000\)
题解
显然是LCT。
那么要维护什么呢?
先看看DP方程:设\(f_{i,0}\)为以\(i\)为根的子树中\(i\)这个点不选的答案,\(f_{i,1}\)为\(i\)这个点选的答案。显然
f_{i,0}&=\sum_{v}\max(f_{v,0},f_{v,1})\\
f_{i,1}&=1+\sum_v f_{v,0}
\end{align}
\]
先看看一条链要怎么做。设\(s_{i,j}\)为某一段中第一个点的状态为\(i\),在后面补一个状态为\(j\)的点时这一段的贡献。这个东西很容易合并。
只有一个点时
s_{0,0}&=0\\
s_{0,1}&=0\\
s_{1,0}&=1\\
s_{1,1}&=-\infty
\end{align}
\]
那树上要怎么做?
容易观察到\(i\)的各个儿子之间是互不影响的。可以像这道题一样,把整棵树剖成轻重链,每个点的贡献要加上这个点的轻儿子的贡献。
access和link时处理一下即可。
时间复杂度:\(O(n\log n)\)
题解
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
#include<functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void sort(int &a,int &b)
{
if(a>b)
swap(a,b);
}
void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[100];
sprintf(str,"%s.in",s);
freopen(str,"r",stdin);
sprintf(str,"%s.out",s);
freopen(str,"w",stdout);
#endif
}
int rd()
{
int s=0,c;
while((c=getchar())<'0'||c>'9');
do
{
s=s*10+c-'0';
}
while((c=getchar())>='0'&&c<='9');
return s;
}
void put(int x)
{
if(!x)
{
putchar('0');
return;
}
static int c[20];
int t=0;
while(x)
{
c[++t]=x%10;
x/=10;
}
while(t)
putchar(c[t--]+'0');
}
int upmin(int &a,int b)
{
if(b<a)
{
a=b;
return 1;
}
return 0;
}
int upmax(int &a,int b)
{
if(b>a)
{
a=b;
return 1;
}
return 0;
}
struct p
{
ll s11,s12,s21,s22;
p()
{
s11=s12=s21=s22=0;
}
};
p merge(p a,p b)
{
p c;
c.s11=max(a.s11+b.s11,a.s12+b.s21);
c.s12=max(a.s11+b.s12,a.s12+b.s22);
c.s21=max(a.s21+b.s11,a.s22+b.s21);
c.s22=max(a.s21+b.s12,a.s22+b.s22);
return c;
}
void add(p &a,ll s11,ll s12,ll s21,ll s22)
{
a.s11+=s11;
a.s12+=s12;
a.s21+=s21;
a.s22+=s22;
}
namespace lct
{
int f[300010];
int a[300010][2];
p v[300010];
p s[300010];
int root(int x)
{
return !f[x]||(a[f[x]][0]!=x&&a[f[x]][1]!=x);
}
void mt(int x)
{
s[x]=v[x];
if(a[x][0])
s[x]=merge(s[a[x][0]],s[x]);
if(a[x][1])
s[x]=merge(s[x],s[a[x][1]]);
}
void rotate(int x)
{
int p=f[x];
int q=f[p];
int ps=(x==a[p][1]);
int qs=(p==a[q][1]);
int ch=a[x][ps^1];
if(!root(p))
a[q][qs]=x;
a[x][ps^1]=p;
a[p][ps]=ch;
if(ch)
f[ch]=p;
f[p]=x;
f[x]=q;
mt(p);
}
void splay(int x)
{
while(!root(x))
{
int p=f[x];
if(!root(p))
{
int q=f[p];
if((p==a[q][1])==(x==a[p][1]))
rotate(p);
else
rotate(x);
}
rotate(x);
}
mt(x);
}
void access(int x)
{
int y=x;
int t=0;
while(x)
{
splay(x);
add(v[x],max(s[a[x][1]].s21,s[a[x][1]].s22),max(s[a[x][1]].s21,s[a[x][1]].s22),max(max(s[a[x][1]].s11,s[a[x][1]].s12),max(s[a[x][1]].s21,s[a[x][1]].s22)),max(max(s[a[x][1]].s11,s[a[x][1]].s12),max(s[a[x][1]].s21,s[a[x][1]].s22)));
add(v[x],-max(s[t].s21,s[t].s22),-max(s[t].s21,s[t].s22),-max(max(s[t].s11,s[t].s12),max(s[t].s21,s[t].s22)),-max(max(s[t].s11,s[t].s12),max(s[t].s21,s[t].s22)));
a[x][1]=t;
mt(x);
t=x;
x=f[x];
}
splay(y);
}
void link(int x,int y)
{
v[x].s11=-0x7fffffff;
v[x].s12=1;
v[x].s21=0;
v[x].s22=0;
mt(x);
access(y);
f[x]=y;
a[y][1]=x;
// add(v[y],1,0);
mt(y);
}
};
int main()
{
open("b");
int n,type;
scanf("%d%d",&n,&type);
int i,x;
int ans=0;
lct::v[1].s11=-0x7fffffff;
lct::v[1].s12=1;
lct::v[1].s21=0;
lct::v[1].s22=0;
lct::mt(1);
for(i=2;i<=n+1;i++)
{
scanf("%d",&x);
if(type)
x^=ans;
x++;
lct::link(i,x);
lct::access(1);
ans=max(max(lct::s[1].s11,lct::s[1].s21),max(lct::s[1].s12,lct::s[1].s22));
printf("%d\n",ans);
}
return 0;
}
【XSY2665】没有上司的舞会 LCT DP的更多相关文章
- 『没有上司的舞会 树形DP』
树形DP入门 有些时候,我们需要在树形结构上进行动态规划来求解最优解. 例如,给定一颗\(N\)个节点的树(通常是无根树,即有\(N-1\)条无向边),我们可以选择任意节点作为根节点从而定义出每一颗子 ...
- 洛谷P1352 没有上司的舞会——树形DP
第一次自己写树形DP的题,发个博客纪念`- 题目来源:P1352 没有上司的舞会 题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结 ...
- CodeVS1380 没有上司的舞会 [树形DP]
题目传送门 没有上司的舞会 题目描述 Description Ural大学有N个职员,编号为1~N.他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.每个职员有一个 ...
- P1352 没有上司的舞会——树形DP入门
P1352 没有上司的舞会 题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员 ...
- wikioi 1380 没有上司的舞会 树形dp
1380 没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Ural大学有N个职员,编号为1~N.他 ...
- [luogu]P1352 没有上司的舞会[树形DP]
本Lowbee第一次写树形DP啊,弱...一个变量写错半天没看出来...... 题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点 ...
- 没有上司的舞会 树形dp
题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri, ...
- P1352 没有上司的舞会[树形dp]
题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri, ...
- P1352 没有上司的舞会&&树形DP入门
https://www.luogu.com.cn/problem/P1352 题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的 ...
随机推荐
- IIS6下使用多域名和通配符证书
由于SSL协议,在完成握手以前,都只能采用IP地址通信方式,没有办法获取访问地址中的域名信息,所以针对每个IP地址的每个端口,服务器只能返回相同的一张证书.如果要实现多个不同域名共享一个IP地址的缺省 ...
- Python Revisited Day 04 (控制结构与函数)
目录 4.1 控制结构 4.1.1 条件分支 4.1.2 循环 4.2 异常处理 4.2.1 捕获与产生异常 4.2.2 自定义异常 4.3 自定义函数 Tips 参数默认值为可变时 危险 4.3.1 ...
- Python—模块介绍
什么是模块? 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码 ...
- Javascript模板引擎handlebars使用
源地址:http://rfyiamcool.blog.51cto.com/1030776/1278620 代码示例: <!DOCTYPE html> <html> <he ...
- Django之admin中管理models中的表格
Django之admin中管理models中的表格 django中使用admin管理models中的表格时,如何将表格注册到admin中呢? 具体操作就是在项目文件夹中的app文件夹中的admin中注 ...
- CodeIgniter框架通过URL向控制器传递参数
通过URL传递参数的方法是GET,在CodeIgnter框架中,通过URL有两种方式向控制器传递参数: 一种是键值对的形式. 一种是类似于文件路径的形式,这个时候,不是以键值对的形式了,我们只传递值. ...
- Zabbix appliance manual
https://www.zabbix.com/documentation/4.0/manual/appliance If the appliance fails to start up in Hype ...
- python基础之数据类型和数值类型
python3的六大数据类型: 1.tuple元组 2.number数字 3.string字符串 4.set集合 5.list列表 6.dictionary字典 其中不可变数据3个:tuple.num ...
- Pycharm中怎么给字典中的多个键-值对同时加上单引号
今天看了个爬虫视频,崔庆才讲师的免费视频, 里面一个批量给header加引号2s完成,这波操作让我眼前一亮. 最终还是发现了骚操作的背后手速是真的快. pycharm中按ctrl+r 勾选右上角的Re ...
- css太极
自己用css做的太极,留个纪念. 用css做太极有很多种实现方法,我这种大概是最简单的了吧,因为div用得太多了,哈哈. 高级一点的应该是用伪类:before和:after去减少div的用量(手动滑稽 ...