【日常小测】没有上司的舞会

  • 题目来源:湖师大附中集训Day1T2
  • 本文为博主原创,未经许可不得转载

题目要求动态维护最大独立集

我们给每个点黑白染色:

(1)叶子是黑色的

(2)若一个点是黑色的,则它的父亲是白色的

(3)若一个点的所有孩子都是白色的,则它本身是黑色的

答案即为黑色点数

从匹配或者独立集问题入手,考虑问题在树上的贪心性质,都能发现上述结论

显然每加入一个新的叶子,会翻转一条链的颜色

考虑用Link_Cut_Tree维护颜色,保证重链上的点的颜色黑白交替

加入一个叶子后,对该叶子进行特殊的access操作,得到一条尽可能长的链

翻转链的颜色(打标记实现),然后根据链顶颜色判断是否ans++

好妙的动态树操作啊(第一见到这种操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include<bits/stdc++.h>
#define FILE "read"
#define MAXN 300100
using namespace std;
int n,type;
inline int read(){
int x=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch=getchar();}
while(ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
class Link_Cut_Tree{
private:
int tot,f[MAXN],col[MAXN],cnt[MAXN],tag[MAXN],st[MAXN],son[MAXN][2];
inline bool isroot(int x){return son[f[x]][0]!=x&&son[f[x]][1]!=x;}
inline bool get(int x){return son[f[x]][1]==x;}
void pushdown(int x){
if(tag[x]){
if(son[x][0]) tag[son[x][0]]^=1,col[son[x][0]]^=1;
if(son[x][1]) tag[son[x][1]]^=1,col[son[x][1]]^=1;
tag[x]=0;
}
}
inline void rotate(int x){
int y=f[x],z=f[y],which=get(x);
if(!isroot(y)) son[z][son[z][1]==y]=x;
son[y][which]=son[x][which^1]; f[son[y][which]]=y;
son[x][which^1]=y; f[y]=x; f[x]=z;
}
inline void splay(int x){
int top=0; st[++top]=x;
for(int i=x;!isroot(i);i=f[i]) st[++top]=f[i];
for(int i=top;i;--i) pushdown(st[i]);
for(int y=f[x];!isroot(x);rotate(x),y=f[x])
if(!isroot(y)) rotate(get(x)==get(y)?y:x);
}
inline int find(int x){
while(son[x][0]) x=son[x][0];
splay(x); return x;
}
inline int access(int x,int y){
while(x){
splay(x);
int z=son[x][1];
if(z) son[x][1]=0,cnt[x]+=(col[find(z)]==0);
if(col[y]==1) {if(col[x]==1) break;}
else{
if(cnt[x]>1) break;
--cnt[x];
}
son[x][1]=y; f[y]=x;
y=find(x); x=f[y];
}
tag[y]^=1; col[y]^=1;
if(col[y]){
cnt[f[y]]--;
return 0;
}
else{
cnt[f[y]]++;
return 1;
}
}
public:
void init(){tot=1; col[0]=1;}
int insert(int y){
int x=++tot;
f[x]=y; col[x]=1;
return access(y,x);
}
}Tree;
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
n=read(); type=read(); Tree.init(); int ans=1;
for(int i=1;i<=n;++i){
int x=read(); if(type&&i>1) x^=ans;
ans+=Tree.insert(x+1);
printf("%d\n",ans);
}
return 0;
}
文章目录
,