【SPOJ】QTREE7(Link-Cut Tree)

题面

洛谷

Vjudge

题解

QTREE6的本质是一样的:维护同色联通块

那么,QTREE6同理,对于两种颜色分别维护一棵\(LCT\)

每次只修改和它父亲的连边。

考虑如何维护最大值

因为每次\(access\)会删去一个数,所以我们肯定不能够只维护最大值。

因此,对于每一个节点,额外维护一个\(multiset\)(当然,可删堆,\(map\)之类的也行)

每次用\(multiset\)维护虚子树的最值,拿过去更新即可。

最后的答案和QTREE6是一样的,

找到这个联通块的最浅父亲,维护一下子树最值就行啦。

#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;
}
int W[MAX];
struct Link_Cut_Tree
{
struct Node
{
int ch[2],ff;
int mx;
multiset<int> S;
}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].mx=max(max(t[ls].mx,t[rs].mx),W[x]);
if(!t[x].S.empty())t[x].mx=max(t[x].mx,*t[x].S.rbegin());
}
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);
if(rs)t[x].S.insert(t[rs].mx);
rs=y;
if(rs)t[x].S.erase(t[rs].mx);
pushup(x);
}
}
int findroot(int x){access(x);Splay(x);while(ls)x=ls;Splay(x);return x;}
void link(int x,int y){if(!y)return;access(y);Splay(y);Splay(x);t[x].ff=y;t[y].ch[1]=x;pushup(y);}
void cut(int x,int y){if(!y)return;access(x);Splay(x);ls=t[ls].ff=0;pushup(x);}
}LCT[2];
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1,fa[MAX],n,Q,c[MAX];
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
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;
fa[v]=u;LCT[c[v]].link(v,u);dfs(v,u);
}
}
int main()
{
n=read();
for(int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v),Add(v,u);
for(int i=1;i<=n;++i)c[i]=read();
for(int i=1;i<=n;++i)W[i]=read();
LCT[0].t[0].mx=LCT[1].t[0].mx=-2e9;
dfs(1,0);Q=read();
while(Q--)
{
int opt=read(),u=read();
if(opt==0)
{
int ff=LCT[c[u]].findroot(u);
if(c[u]==c[ff])printf("%d\n",LCT[c[u]].t[ff].mx);
else printf("%d\n",LCT[c[u]].t[LCT[c[u]].t[ff].ch[1]].mx);
}
else if(opt==1)LCT[c[u]].cut(u,fa[u]),c[u]^=1,LCT[c[u]].link(u,fa[u]);
else
{
LCT[c[u]].access(u);LCT[c[u]].Splay(u);
W[u]=read();LCT[c[u]].pushup(u);
}
}
return 0;
}

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

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

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

  2. LCT(Link Cut Tree)总结

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

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

    [SPOJ]QTREE6(Link-Cut-Tree) 题面 Vjudge 题解 很神奇的一道题目 我们发现点有黑白两种,又是动态加边/删边 不难想到\(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. 【MYSQL安装】mysql 5.6在centos6.4上的安装

    1.卸载系统自带的mysql [root@zhangmeng ~]# rpm -qa |grep mysql mysql-libs--.el6_3.x86_64 [root@zhangmeng ~]# ...

  2. Arduino语言

    Arduino语言 Arduino语言是建立在C/C++基础上的,其实也就是基础的C语言,Arduino语言只不过把AVR单片机(微控制器)相关的一些参数设置都函数化,不用我们去了解他的底层,让我们不 ...

  3. php常用的几个预定义变量

    __FILE__:返回所在路径文件名和文件名称 __DIR__:返回文件所在的完整目录 __LINE__:返回当前文件代码的行号 __CLASS__:返回当前类名 __FUNCTION__:返回当前方 ...

  4. 接口自动化·分享·第二篇·你必须了解的HttpRequest和HttpResponse

    完成一个接口调用其实就是完成了一次http请求,所以你必须要清楚一个http请求的组成. 一次完整的请求包含:请求+响应. 一.HttpRequest请求对象 要调用一个接口,首先要准备的是一个请求对 ...

  5. appium自动化环境搭建

    1.java开发环境JDK 2.android SDK(platform/platform tools/tools/build tools) 3.python下载安装(pip) 4.appium下载安 ...

  6. elasticsearch备份与恢复

    备注:以下代码在kibana插件下运行: # 创建一个备份用的仓库# type:fs文件系统# 支持Shared filesystem, Amazon S3, HDFS和Azure #Cloud# l ...

  7. ArcFace Demo [Android]

    Free SDK demo 工程如何使用? 1.下载代码:git clone https://github.com/asdfqwrasdf/ArcFaceDemo.git 或者直接下载压缩包 2.前往 ...

  8. linux-ubuntu配置通过22端口远程连接

    当安装好ubuntu后获取到对应主机的ip地址,要想通过类似xshell这样的远程连接工具连接到ubuntu主机,需要在你刚刚安装好的ubuntu主机上安装openssh这个软件,才能通过远程来连接u ...

  9. 基于DPDK的高效数据包捕获技术分析与应用

    被NFV的论文折磨了两天,今天上午看了两篇DPDK的综述. 传统的包捕获机制 1. BPF 两个组成部分:转发部分和过滤部分. 转发部分负责从链路层提取数据包并转发给过滤部分. 过滤部分根据过滤规则, ...

  10. Python安装Numpy,matplotlib库

    <1> Numpy是一款基于python的功能强大的科学计算包.要安装numpy首先你得先安装python. python的安装非常简单,本人安装的是python2.7 具体安装步骤如下: ...