【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.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的 ...
随机推荐
- Python全栈开发之路 【第四篇】:Python基础之函数
本节内容 函数def: 1.位置参数,默认参数 2.位置参数,关键参数 3.如果参数中出现 *users,传递的参数就可以不再是固定的个数, 传过来的所有元素进行打包成元组 *args,**kwarg ...
- H5 24-CSS三大特性之继承性
24-CSS三大特性之继承性 我是段落 我是段落 我是超链接 我是大标题 <!DOCTYPE html> <html lang="en"> <head ...
- php 简单的学习GD库绘制图片并传回给前端实现方式
1.基本的GD库绘制图片汇总 2.后台实现小案例 <?php // $img = imagecreatetruecolor(200,40); // var_dump($img); // 利用GD ...
- Python之加环境变量
1.python找文件是先去当前文件所在的文件夹下找,也就是bin目录下找 2.如果bin目录里找不到,再去python的环境变量里找 如果有pycharm,那么直接点右键-选择Mark Direct ...
- 【学习总结】 小白CS成长之路
2017-9-3:入坑. 理想:敲着代码唱着歌. 现实:骨感. Step 1: 认识CS: CS大体可以分成以下几个大领域:硬件.系统.软件.网络.计算理论.计算方法. 硬 件 ---- 数字电路.集 ...
- Nginx会话保持之nginx-sticky-module模块
Nginx会话保持之nginx-sticky-module模块 - 天行健,君子以自强不息:地势坤,君子以厚德载物. - CSDN博客https://blog.csdn.net/huangjinjin ...
- Python3练习题 021:递归方法求阶乘
利用递归方法求5!. 方法一 f = 1 for i in range(1,6): f = f * i print(f) 方法二 import functools print(functo ...
- VUE.JS 使用axios数据请求时数据绑定时 报错 TypeError: Cannot set property 'xxxx' of undefined 的解决办法
正常情况下在data里面都有做了定义 在函数里面进行赋值 这时候你运行时会发现,数据可以请求到,但是会报错 TypeError: Cannot set property 'listgroup' of ...
- MySQL简介及安装
一.DBA工作内容及课程体系 二.MySQL课程体系介绍 三.DBA的职业素养 四.MySQL简介及安装 01 什么是数据? 02 什么是数据库管理系统 03 数据库管理系统种类 04 MySQL发展 ...
- NOIP2016提高组复赛C 愤怒的小鸟
题目链接:http://uoj.ac/problem/265 题目大意: 太长了不想概括... 分析: 状压DP的模板题,把所有可能的抛物线用二进制表示,然后暴力枚举所有组合,详情见代码内注释 代码如 ...