【NOI2017模拟6.22】没有上司的舞会
来源:互联网 发布:外国域名注册机构 编辑:程序博客网 时间:2024/06/05 16:37
题目大意
只有加点操作,动态维护树的最大独立集
题解
考虑LCT,对于一个点x,s[x][0/1]表示x选或不选时不与他在同一条链上的儿子的DP值,f[x][0/1][0/1]表示splay中x维护的这一个区间最左端选或不选以及最右端选或不选的DP值,只要在切掉splay的边或连接时维护s就好了
代码
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<set>#include<bitset>#include<map>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;typedef long long LL;typedef double db;int get(){ char ch; while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-'); if (ch=='-'){ int s=0; while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0'; return -s; } int s=ch-'0'; while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0'; return s;}const int N = 300010;struct node{ int s[2]; int f[2][2]; int* operator [](int x){return f[x];}}tree[N];int fa[N];int s[N][2];int n;int pd(int x){ if (x==tree[fa[x]].s[0])return 0; if (x==tree[fa[x]].s[1])return 1; return -1;}void update(int x){ int ls=tree[x].s[0],rs=tree[x].s[1]; if (!ls&&!rs){ tree[x][0][1]=tree[x][1][0]=0; tree[x][0][0]=s[x][0]; tree[x][1][1]=s[x][1]+1; return; } if (ls&&rs) fo(a,0,1) fo(b,0,1) tree[x][a][b]=max(tree[ls][a][0]+s[x][1]+tree[rs][0][b]+1,max(tree[ls][a][0],tree[ls][a][1])+s[x][0]+max(tree[rs][0][b],tree[rs][1][b])); else if (ls){ fo(a,0,1){ tree[x][a][1]=tree[ls][a][0]+s[x][1]+1; tree[x][a][0]=max(tree[ls][a][0],tree[ls][a][1])+s[x][0]; } } else{ fo(b,0,1){ tree[x][1][b]=tree[rs][0][b]+s[x][1]+1; tree[x][0][b]=s[x][0]+max(tree[rs][0][b],tree[rs][1][b]); } }}void split(int x){ int y=tree[x].s[1]; s[x][0]+=max(max(tree[y][0][0],tree[y][0][1]),max(tree[y][1][0],tree[y][1][1])); s[x][1]+=max(tree[y][0][0],tree[y][0][1]); tree[x].s[1]=0; update(x);}void merge(int x,int y){ s[x][0]-=max(max(tree[y][0][0],tree[y][0][1]),max(tree[y][1][0],tree[y][1][1])); s[x][1]-=max(tree[y][0][0],tree[y][0][1]); tree[x].s[1]=y; update(x);}void rotate(int x){ int y=fa[x],z=fa[y]; int tx=pd(x),ty=pd(y); if (ty!=-1)tree[z].s[ty]=x; fa[x]=z; if (tree[x].s[tx^1])fa[tree[x].s[tx^1]]=y; tree[y].s[tx]=tree[x].s[tx^1]; tree[x].s[tx^1]=y; fa[y]=x; update(y); update(x); if (ty!=-1)update(z);}void splay(int x){ while(pd(x)!=-1){ if (pd(fa[x])!=-1){ if (pd(fa[x])==pd(x))rotate(fa[x]); else rotate(x); } rotate(x); }}void access(int x){ splay(x); if (tree[x].s[1])split(x); while(fa[x]){ int y=fa[x]; splay(y); if (tree[y].s[1])split(y); merge(y,x); update(x); x=y; }}int main(){ freopen("party.in","r",stdin); freopen("party.out","w",stdout); n=get(); int ty=get(); int ans=0; tree[1][1][1]=1; tree[1][0][0]=0; fo(i,2,n+1){ int x=get(); x=x^(ans*ty); x++; fa[i]=x; access(x); splay(x); tree[i][1][1]=1; tree[i][0][0]=0; s[x][0]++; update(x); fo(a,0,1) fo(b,0,1) ans=max(ans,tree[x][a][b]); printf("%d\n",ans); } fclose(stdin); fclose(stdout); return 0;}
阅读全文
0 0
- 【NOI2017模拟6.22】没有上司的舞会
- 没有上司的舞会
- 没有上司的舞会
- 没有上司的舞会
- 没有上司的舞会
- 没有上司的舞会
- 没有上司的舞会
- 没有上司的舞会
- 没有上司的舞会
- 没有上司的舞会
- 没有上司的舞会
- 1380 没有上司的舞会
- 1380 没有上司的舞会
- Codevs1380 没有上司的舞会
- codevs 没有上司的舞会
- codevs1380 没有上司的舞会
- [tyvj1052]没有上司的舞会
- 【u024】没有上司的舞会
- 堆和栈的区别
- 操作系统之进程切换
- Web前端-写给大家看的设计书-笔记-设计原则
- jQuery选择器
- struts拦截器使用
- 【NOI2017模拟6.22】没有上司的舞会
- php 连接mysql数据库,查询、插入、更新、删除功能
- 【面向对象设计原则】之 单一职责原则(SRP)
- SpringSecurity下做POST测试以及传递实体
- react-native 学习 ----- React Navigation
- MongoDB学习1
- 【Java基础 四】---异常处理
- 通过ThreadLocal和Filter实现请求上下文【旧】
- android控件09---TabHost