分析

[BZOJ3779]重组病毒唯一的区别是多了一个链上求实链段数的操作。

因为每条实链的颜色必然不相同且一条实链上不会有两个深度相同的点(好像算法的正确性和第二个条件没什么关系,算了算了),画图分析可得,如果用\(dis[x]\)表示从\(x\)到根结点路径上的实链段数,则\(x\)到\(y\)路径上的实链段数可以表示为:

\[dis[x]+dis[y]-dis[lca(x,y)]*2+1
\]

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
using std::cin;
using std::cout;
using std::endl;
typedef long long LL; inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x;
} const int MAXN=100005;
int n,m;
int ecnt,head[MAXN];
int fa[MAXN],dep[MAXN],siz[MAXN],pc[MAXN];
int top[MAXN],id[MAXN],num[MAXN],tot;
int maxn[MAXN<<2],atag[MAXN<<2],loc,ql,qr,kk;
int sta[MAXN],statop; struct Edge{
int to,nxt;
}e[MAXN<<1]; inline void add_edge(int bg,int ed){
ecnt++;
e[ecnt].to=ed;
e[ecnt].nxt=head[bg];
head[bg]=ecnt;
} struct lct{
int fa,ch[2];
int tag;
}a[MAXN]; inline void subupd(int x,int kkk); inline int subquery(int x); #define lc a[x].ch[0]
#define rc a[x].ch[1]
inline bool isroot(int x){
return a[a[x].fa].ch[0]!=x&&a[a[x].fa].ch[1]!=x;
} inline void pushr(int x){
std::swap(lc,rc);
a[x].tag^=1;
} inline void pushdown(int x){
if(!a[x].tag) return;
if(lc) pushr(lc);
if(rc) pushr(rc);
a[x].tag=0;
} inline void rotate(int x){
int y=a[x].fa,z=a[y].fa;
int f=(a[y].ch[1]==x),g=a[x].ch[f^1];
if(!isroot(y)) a[z].ch[a[z].ch[1]==y]=x;
a[x].ch[f^1]=y;
a[y].ch[f]=g;
if(g) a[g].fa=y;
a[y].fa=x;
a[x].fa=z;
} inline void splay(int x){
int y=x,z;
statop=1;
sta[1]=y;
while(!isroot(y)) sta[++statop]=y=a[y].fa;
while(statop) pushdown(sta[statop--]);
while(!isroot(x)){
y=a[x].fa,z=a[y].fa;
if(!isroot(y)){
if((a[y].ch[0]==x)==(a[z].ch[0]==y)) rotate(y);
else rotate(x);
}
rotate(x);
}
} inline int findroot(int x){
while(pushdown(x),lc) x=lc;
return x;
} inline void access(int x){
for(int y=0;x;x=a[y=x].fa){
splay(x);
if(rc) subupd(findroot(rc),1);
rc=y;
if(rc) subupd(findroot(rc),-1);
}
}
#undef lc
#undef rc void dfs1(int x,int pre,int depth){
fa[x]=pre;
a[x].fa=pre;
dep[x]=depth;
siz[x]=1;
int maxsiz=-1;
trav(i,x){
int ver=e[i].to;
if(ver==pre) continue;
dfs1(ver,x,depth+1);
siz[x]+=siz[ver];
if(siz[ver]>maxsiz){
maxsiz=siz[ver];
pc[x]=ver;
}
}
} void dfs2(int x,int topf){
top[x]=topf;
id[x]=++tot;
num[tot]=x;
if(!pc[x]) return;
dfs2(pc[x],topf);
trav(i,x){
int ver=e[i].to;
if(ver==fa[x]||ver==pc[x]) continue;
dfs2(ver,ver);
}
} #define mid ((l+r)>>1)
#define lc (o<<1)
#define rc ((o<<1)|1)
void build(int o,int l,int r){
if(l==r){
maxn[o]=dep[num[l]];
return;
}
build(lc,l,mid);
build(rc,mid+1,r);
maxn[o]=std::max(maxn[lc],maxn[rc]);
} inline void segpushdown(int o){
if(!atag[o]) return;
maxn[lc]+=atag[o];
maxn[rc]+=atag[o];
atag[lc]+=atag[o];
atag[rc]+=atag[o];
atag[o]=0;
} void upd(int o,int l,int r){
if(ql<=l&&r<=qr){
maxn[o]+=kk;
atag[o]+=kk;
return;
}
segpushdown(o);
if(mid>=ql) upd(lc,l,mid);
if(mid<qr) upd(rc,mid+1,r);
maxn[o]=std::max(maxn[lc],maxn[rc]);
} int squery(int o,int l,int r){
if(l==r) return maxn[o];
segpushdown(o);
if(loc<=mid) return squery(lc,l,mid);
else return squery(rc,mid+1,r);
} int rquery(int o,int l,int r){
if(ql<=l&&r<=qr) return maxn[o];
segpushdown(o);
int ret=0;
if(mid>=ql) ret=std::max(ret,rquery(lc,l,mid));
if(mid<qr) ret=std::max(ret,rquery(rc,mid+1,r));
return ret;
}
#undef mid
#undef lc
#undef rc inline int lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
} inline void subupd(int x,int kkk){
ql=id[x],qr=id[x]+siz[x]-1,kk=kkk;
upd(1,1,n);
} inline int subquery(int x){
ql=id[x],qr=id[x]+siz[x]-1;
return rquery(1,1,n);
} int main(){
n=read(),m=read();
rin(i,2,n){
int u=read(),v=read();
add_edge(u,v);
add_edge(v,u);
}
dfs1(1,0,1);
dfs2(1,1);
build(1,1,n);
while(m--){
int opt=read();
if(opt==1){
int x=read();
access(x);
}
else if(opt==2){
int ans=0;
int x=read(),y=read();
loc=id[x];ans+=squery(1,1,n);
loc=id[y];ans+=squery(1,1,n);
loc=id[lca(x,y)];ans-=(squery(1,1,n)<<1);
ans++;
printf("%d\n",ans);
}
else{
int x=read();
printf("%d\n",subquery(x));
}
}
return 0;
}

[BZOJ4817][SDOI2017]树点涂色:Link-Cut Tree+线段树的更多相关文章

  1. 【BZOJ4817】树点涂色(LCT,线段树,树链剖分)

    [BZOJ4817]树点涂色(LCT,线段树,树链剖分) 题面 BZOJ Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义 ...

  2. [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 692  Solved: 408[Submit][Status ...

  3. P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA

    \(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...

  4. bzoj4817/luogu3703 树点涂色 (LCT+dfs序+线段树)

    我们发现,这个染色的操作他就很像LCT中access的操作(为什么??),然后就自然而然地想到,其实一个某条路径上的颜色数量,就是我们做一个只有access操作的LCT,这条路径经过的splay的数量 ...

  5. BZOJ.4817.[SDOI2017]树点涂色(LCT DFS序 线段树)

    题目链接 操作\(1.2\)裸树剖,但是操作\(3\)每个点的答案\(val\)很不好维护.. 如果我们把同种颜色的点划分到同一连通块中,那么向根染色的过程就是Access()! 最初所有点间都是虚边 ...

  6. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  7. Link Cut Tree 动态树 小结

    动态树有些类似 树链剖分+并查集 的思想,是用splay维护的 lct的根是动态的,"轻重链"也是动态的,所以并没有真正的轻重链 动态树的操作核心是把你要把 修改/询问/... 等 ...

  8. LCT(link cut tree) 动态树

    模板参考:https://blog.csdn.net/saramanda/article/details/55253627 综合各位大大博客后整理的模板: #include<iostream&g ...

  9. 洛谷.3690.[模板]Link Cut Tree(动态树)

    题目链接 LCT(良心总结) #include <cstdio> #include <cctype> #include <algorithm> #define gc ...

随机推荐

  1. 20191127 Spring Boot官方文档学习(4.13)

    4.13.Messaging Spring框架为与消息传递系统集成提供了广泛的支持,从使用JmsTemplate简化JMS API到完整的异步接收消息的基础结构.Spring AMQP为高级消息队列协 ...

  2. 第十四周总结 Io之文件流

    I/O相关 输入/输出 流(数据流动) 数据流动的方向 读数据(输入input) 写数据(输出output) 文件流 字符流 数据流 对象流 网络流.... 1.什么叫文件 一种电脑的存储方式 文件有 ...

  3. java.io.IOException: Cannot run program "/opt/jdk1.8.0_191/bin/java" (in directory "/var/lib/jenkins/workspace/xinguan"): error=2, No such file or directory

    测试jenkins构建,报错如下 Parsing POMs Established TCP socket on 44463 [xinguan] $ /opt/jdk1.8.0_191/bin/java ...

  4. 【转】mysqldump原理探究

    作者:胡儿胡儿 来源:CSDN 原文:https://blog.csdn.net/cug_jiang126com/article/details/49824471 —————————————————— ...

  5. Nginx 的方向代理及配置

    最近有打算研读nginx源代码,看到网上介绍nginx可以作为一个反向代理服务器完成负载均衡.所以搜罗了一些关于反向代理服务器的内容,整理综合. 一  概述 反向代理(Reverse Proxy)方式 ...

  6. P1219八皇后

    这个题是一道USACO的经典dfs,与我见面的时间起码七个月了. 放置n个皇后于n*n棋盘,他们不能互相吃(行,列,对角线),问有几种摆法?于是想到了dfs(自我认为有图的就不用DP).首先确定好了要 ...

  7. Qt 遍历不规则树的节点

    在使用Qt的GraphicsScene作图时,遇到类似这样的需求:在scene中创建节点类似下图, 现在我要把每个节点的txt保存到xml文件中,结构为 <?xml version='1.0' ...

  8. 2017第二届广东省强网杯线上赛--Nonstandard

    测试文件:http://static2.ichunqiu.com/icq/resources/fileupload/CTF/echunqiu/qwb/Nonstandard_26195e1832795 ...

  9. 移动端布局的思考和rem的设置

    如下方法如有不正确的地方,欢迎指正 前提: 设置稿750px 目标:40px = 1rem js设置方法:(小于等于750屏幕等比缩放) ;(function (doc, win, undefined ...

  10. Nginx cpu亲和性调整

    意义 Nginx默认没有开启利用多核cpu,我们可以通过worker_processes指令来启动多个worker,但是worker最终运行在哪些cpu核上是系统层进行调度的:我们可以通过增加work ...