【SPOJ】QTREE6(Link-Cut-Tree)

题面

Vjudge

题解

很神奇的一道题目

我们发现点有黑白两种,又是动态加边/删边

不难想到\(LCT\)

最爆力的做法,显然是每次修改单点颜色的时候

暴力修改当前点和它的父亲以及儿子之间的连边状态

但是这样显然是假的(菊花树了解一下)

怎么优化呢?

对于每次操作,我们考虑如何只修改一次。

对于树上的一个结点,如果只修改一次,显然是修改和其父亲的状态。

那么,我们在考虑\(LCT\)的连边操作的时候,

如果当前点变色,那么就只修改和它父亲的连边。

这样怎么算答案呢?

如果我们确定树是一棵有根树

那么,我们只需要找到当前点深度最浅的父亲

这个父亲在当前颜色的树上的儿子个数显然就是答案

所以,我们只需要每次只修改当前点和其父亲的关系就行了。

但是要注意一个问题,因为强制是有根树了。

所以打死都不能有\(makeroot\)操作

所以\(link,cut\)之类的都要魔改一发了。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 111111
#define ls (t[x].ch[0])
#define rs (t[x].ch[1])
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
struct Link_Cut_Tree
{
struct Node
{
int ch[2],ff;
int size,sum;
int rev;
}t[MAX];
bool isroot(int x){return t[t[x].ff].ch[0]!=x&&t[t[x].ff].ch[1]!=x;}
void pushup(int x){t[x].sum=t[ls].sum+t[rs].sum+t[x].size+1;}
void rotate(int x)
{
int y=t[x].ff,z=t[y].ff;
int k=t[y].ch[1]==x;
if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;t[y].ff=x;
pushup(y);pushup(x);
}
void Splay(int x)
{
while(!isroot(x))
{
int y=t[x].ff,z=t[y].ff;
if(!isroot(y))
(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
pushup(x);
}
void access(int x)
{
for(int y=0;x;y=x,x=t[x].ff)
{
Splay(x);t[x].size+=t[rs].sum-t[y].sum;
rs=y;pushup(x);
}
}
void link(int x,int y){if(!y)return;access(y);Splay(x);Splay(y);t[x].ff=y;t[y].size+=t[x].sum;pushup(y);}
void cut(int x,int y){if(!y)return;access(x);Splay(x);ls=t[ls].ff=0;pushup(x);}
int findroot(int x){access(x);Splay(x);while(ls)x=ls;Splay(x);return x;}
}LCT[2];
int n,m,fa[MAX],c[MAX];
void dfs(int u,int ff)
{
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(v==ff)continue;
LCT[1].link(v,u);fa[v]=u;
dfs(v,u);
}
}
int main()
{
n=read();
for(int i=1;i<=n;++i)c[i]=1;
for(int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v),Add(v,u);
dfs(1,0);
m=read();
while(m--)
{
int opt=read(),x=read();
if(opt)LCT[c[x]].cut(x,fa[x]),c[x]^=1,LCT[c[x]].link(x,fa[x]);
else
{
LCT[c[x]].access(x);
int ff=LCT[c[x]].findroot(x);
if(c[ff]==c[x])printf("%d\n",LCT[c[x]].t[ff].sum);
else printf("%d\n",LCT[c[x]].t[LCT[c[x]].t[ff].ch[1]].sum);
}
}
return 0;
}

【SPOJ】QTREE6(Link-Cut-Tree)的更多相关文章

  1. 【SPOJ】Highways(矩阵树定理)

    [SPOJ]Highways(矩阵树定理) 题面 Vjudge 洛谷 题解 矩阵树定理模板题 无向图的矩阵树定理: 对于一条边\((u,v)\),给邻接矩阵上\(G[u][v],G[v][u]\)加一 ...

  2. LCT(Link Cut Tree)总结

    概念.性质简述 首先介绍一下链剖分的概念链剖分,是指一类对树的边进行轻重划分的操作,这样做的目的是为了减少某些链上的修改.查询等操作的复杂度.目前总共有三类:重链剖分,实链剖分和并不常见的长链剖分. ...

  3. 【SPOJ】QTREE7(Link-Cut Tree)

    [SPOJ]QTREE7(Link-Cut Tree) 题面 洛谷 Vjudge 题解 和QTREE6的本质是一样的:维护同色联通块 那么,QTREE6同理,对于两种颜色分别维护一棵\(LCT\) 每 ...

  4. 【SPOJ】Substrings(后缀自动机)

    [SPOJ]Substrings(后缀自动机) 题面 Vjudge 题意:给定一个长度为\(len\)的串,求出长度为1~len的子串中,出现最多的出现了多少次 题解 出现次数很好处理,就是\(rig ...

  5. 【CF487E】Tourists(圆方树)

    [CF487E]Tourists(圆方树) 题面 UOJ 题解 首先我们不考虑修改,再来想想这道题目. 我们既然要求的是最小值,那么,在经过一个点双的时候,走的一定是具有较小权值的那一侧. 所以说,我 ...

  6. 【CF17E】Palisection(回文树)

    [CF17E]Palisection(回文树) 题面 洛谷 题解 题意: 求有重叠部分的回文子串对的数量 所谓正难则反 求出所有不重叠的即可 求出以一个位置结束的回文串的数量 和以一个位置为开始的回文 ...

  7. 【BZOJ3160】万径人踪灭(FFT,Manacher)

    [BZOJ3160]万径人踪灭(FFT,Manacher) 题面 BZOJ 题解 很容易想到就是满足条件的子序列个数减去回文子串的个数吧... 至于满足条件的子序列 我们可以依次枚举对称轴 如果知道关 ...

  8. 【BZOJ3944】Sum(杜教筛)

    [BZOJ3944]Sum(杜教筛) 题面 求\[\sum_{i=1}^n\mu(i)和\sum_{i=1}^n\phi(i)\] 范围:\(n<2^{31}\) 令\[S(n)=\sum_{i ...

  9. 【BZOJ3730】震波(动态点分治)

    [BZOJ3730]震波(动态点分治) 题面 BZOJ 题意 给定一棵树, 每次询问到一个点的距离\(<=K\)的点的权值之和 动态修改权值, 强制在线 题解 正常的\(DP\)??? 很简单呀 ...

随机推荐

  1. Kettle数据源连接配置

    说明: 通过(图3.1)我们可以看到创建数据源时需要配置相应的参数: Connection Name(必填):配置数据源使用名称,如:Rot_Source Host Name(必填):数据库主机IP地 ...

  2. javaweb(二十六)——jsp简单标签标签库开发(二)

    一.JspFragment类介绍 javax.servlet.jsp.tagext.JspFragment类是在JSP2.0中定义的,它的实例对象代表JSP页面中的一段符合JSP语法规范的JSP片段, ...

  3. php开发文章发布示例(正则表达式实例开发)

    存档: post.php <form method="post" action="viewthread.php" target="_blank& ...

  4. 一个IP可以登几个拼多多后台 拼多多如何推广营销

    想要在拼多多上开双店?担心一根网线会引起IP冲突?那么一根网线可以登几个拼多多后台呢?有数据显示,挂双店是没有问题的,甚至可以多开.那么解决了一根网线的事情,要怎么对自己的店铺进行营销推广呢?下面是小 ...

  5. Git操作指令

    1.创建版本库 git init 2.把工作区修改过的文件添加到版本库暂存区,点号表示当前目录下所有文件; git add .#查看仓库状态git status 3.把版本库暂存区的文件提交到当前分支 ...

  6. Dubbo使用心得2

  7. Qt类继承关系图

    分享两个资源,对于系统了解Qt框架的整体脉络很有帮助. Qt4类关系图+Qt5类关系图,PDF+JPG格式 [下载] Qt5类关系图(基于Qt5.1版),JPG格式[下载]

  8. Linux java项目冲突不能正常运行

    部署项目,在windows环境部署到Tomcat能够正常运行,部署到Linux环境下只能访问一些html资源,不能正常运行. 解决步骤: 1.清除webapps目录下所有文件夹,将war包上传至web ...

  9. c# HttpListener拒绝访问

    直接记录解决步骤: 程序代码: HttpListener httpListener = new HttpListener(); httpListener.Prefixes.Add("http ...

  10. 线段树---poj3468 A Simple Problem with Integers:成段增减:区间求和

    poj3468 A Simple Problem with Integers 题意:O(-1) 思路:O(-1) 线段树功能:update:成段增减 query:区间求和 Sample Input 1 ...