同BZOJ3779。

SDOI出原题,还是弱化版的。

吃枣药丸

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair
#define maxn 200005 int n,m,data[maxn]; namespace Tree{
int h[maxn],to[maxn],ne[maxn],f[maxn][21],en=0,dep[maxn];
int id[maxn],in[maxn],out[maxn],tot=0;
void add(int a,int b)
{to[en]=b;ne[en]=h[a];h[a]=en++;}
void dfs(int o)
{
in[o]=++tot; id[tot]=o;
for (int i=h[o];i>=0;i=ne[i])
if (to[i]!=f[o][0])
f[to[i]][0]=o,dep[to[i]]=dep[o]+1,dfs(to[i]);
out[o]=tot;
}
void init()
{
F(i,1,20)F(j,1,n)f[j][i]=f[f[j][i-1]][i-1];
F(i,1,n) data[in[i]]=dep[i];
// F(i,1,n) printf("%d ",id[i]); printf("\n");
// F(i,1,n) printf("%d ",data[i]);printf("\n");
}
int LCA(int a,int b)
{
if (dep[a]<dep[b]) swap(a,b);
int dist=dep[a]-dep[b];
D(i,20,0) if ((dist>>i)&1) a=f[a][i];
if (a==b) return a;
D(i,20,0) if (f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i];
return f[b][0];
}
} namespace SegTree{
int mx[maxn<<3],tag[maxn<<3];
void update(int o)
{mx[o]=max(mx[o<<1],mx[o<<1|1]);}
void pushdown(int o)
{
if (tag[o]!=0)
{
tag[o<<1]+=tag[o];
tag[o<<1|1]+=tag[o];
mx[o<<1]+=tag[o];
mx[o<<1|1]+=tag[o];
tag[o]=0;
}
}
void build(int o,int l,int r)
{
if (l==r)
{
mx[o]=data[l];
tag[o]=0;
return ;
}
pushdown(o);
int mid=l+r>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
update(o);
}
void modify(int o,int l,int r,int L,int R,int f)
{
if (L<=l&&r<=R)
{
tag[o]+=f;
mx[o]+=f;
return;
}
pushdown(o);
int mid=l+r>>1;
if (R<=mid) return modify(o<<1,l,mid,L,R,f),update(o);
else if (L>mid) return modify(o<<1|1,mid+1,r,L,R,f),update(o);
else return modify(o<<1,l,mid,L,R,f),modify(o<<1|1,mid+1,r,L,R,f),update(o);
}
void add(int a,int f)
{if (!a) return ;modify(1,1,n,Tree::in[a],Tree::out[a],f);}
int querymx(int o,int l,int r,int L,int R)
{
if (L<=l&&r<=R) return mx[o];
pushdown(o);
int mid=l+r>>1;
if (R<=mid) return querymx(o<<1,l,mid,L,R);
else if (L>mid) return querymx(o<<1|1,mid+1,r,L,R);
else return max(querymx(o<<1,l,mid,L,R),querymx(o<<1|1,mid+1,r,L,R));
}
} namespace LCT{
int rev[maxn],fa[maxn],ch[maxn][2],sta[maxn],top=0;
bool isroot(int o)
{return ch[fa[o]][0]!=o&&ch[fa[o]][1]!=o;}
void rot(int x)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0; else l=1; r=l^1;
if (!isroot(y))
{
if (ch[z][0]==y) ch[z][0]=x;
else ch[z][1]=x;
}
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r]; ch[x][r]=y;
}
void pushdown(int x)
{
if (rev[x])
{
rev[x]^=1;
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
}
}
void splay(int x)
{
sta[top=1]=x;
for (int i=x;!isroot(i);i=fa[i]) sta[++top]=fa[i];
while(top) pushdown(sta[top--]); while (!isroot(x))
{
int y=fa[x];
if (!isroot(y))
{
int z=fa[y];
if (ch[z][0]==y^ch[y][0]==x) rot(x);
else rot(y);
}
rot(x);
}
}
int find(int x)
{
pushdown(x);
while (ch[x][0]) x=ch[x][0],pushdown(x);
return x;
}
void access(int x)
{
for (int t=0;x;t=x,x=fa[x])
{
splay(x);
SegTree::add(find(ch[x][1]),1);
ch[x][1]=t;
SegTree::add(find(ch[x][1]),-1);
}
}
} int opt,x,y; int main()
{
scanf("%d%d",&n,&m);
memset(Tree::h,-1,sizeof Tree::h);
F(i,2,n)
{
int a,b;
scanf("%d%d",&a,&b);
Tree::add(a,b);
Tree::add(b,a);
}
Tree::dep[1]=1;Tree::dfs(1);Tree::init();
F(i,1,n) LCT::fa[i]=Tree::f[i][0];
SegTree::build(1,1,n);
F(i,1,m)
{
scanf("%d",&opt);
// cout<<opt<<endl;
switch(opt)
{
case 1: scanf("%d",&x); LCT::access(x); break;
case 2:
scanf("%d%d",&x,&y);
printf("%d\n",SegTree::querymx(1,1,n,Tree::in[x],Tree::in[x])+SegTree::querymx(1,1,n,Tree::in[y],Tree::in[y])+1-2*SegTree::querymx(1,1,n,Tree::in[Tree::LCA(x,y)],Tree::in[Tree::LCA(x,y)])); break;
case 3: scanf("%d",&x); printf("%d\n",SegTree::querymx(1,1,n,Tree::in[x],Tree::out[x]));break;
}
}
}

  

BZOJ 4817 [Sdoi2017]树点涂色 ——LCT 线段树的更多相关文章

  1. [Sdoi2017]树点涂色 [lct 线段树]

    [Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...

  2. 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树

    [BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...

  3. 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]

    树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1 ...

  4. BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)

    题目大意:略 涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上 用$LCT$维护一个树上集合就好 因为它维护了树上集合,所以它别的啥都干不了了 发现树是静态的 ...

  5. [SDOI2017][bzoj4817] 树点涂色 [LCT+线段树]

    题面 传送门 思路 $LCT$ 我们发现,这个1操作,好像非常像$LCT$里面的$Access$啊~ 那么我们尝试把$Access$操作魔改成本题中的涂色 我们令$LCT$中的每一个$splay$链代 ...

  6. BZOJ4817[Sdoi2017]树点涂色——LCT+线段树

    题目描述 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进 ...

  7. bzoj4817 & loj2001 [Sdoi2017]树点涂色 LCT + 线段树

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4817 https://loj.ac/problem/2001 题解 可以发现这个题就是 bzo ...

  8. 【bzoj4817】树点涂色 LCT+线段树+dfs序

    Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...

  9. BZOJ 4817: [Sdoi2017]树点涂色(lct+线段树)

    传送门 解题思路 跟重组病毒这道题很像.只是有了一个询问\(2\)的操作,然后询问\(2\)的答案其实就是\(val[x]+val[y]-2*val[lca(x,y)]+1\)(画图理解).剩下的操作 ...

随机推荐

  1. 字符串转换JSON 的方法

    function (sJSON) { if (window.JSON) { return window.JSON.parse(sJSON); } else { return eval('(' + sJ ...

  2. 2018.2.09 php学习(二)

    1.用索引提高效率: 索引是表的一个概念部分,用来提高检索数据的效率,ORACLE使用了一个复杂的自平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快. 当ORACLE找出执行查询和Upda ...

  3. VA助手添加扩展文件后缀名

    Allow C/C++ files with a non-standard extension Follow these steps to make Visual Assist consider as ...

  4. 脚手架创建一个React项目

    一.安装 1.安装node.js 官网地址 https://nodejs.org/en/ 进入后点击下载,官方网站会根据你的系统类型推荐最适合你安装的版本.(如果已经安装了node.js跳过此步)如下 ...

  5. linux命令行调试邮件服务器

    linux命令行调试邮件服务器 1. Linux客户端调试邮件过程 [root@mxtest ~]# telnet mail.xx.com 25 Trying 172.16.236.103... Co ...

  6. bash编程之循环控制:

    bash编程之循环控制: for varName in LIST; do 循环体 done   while CONDITION; do 循环体 done   until CONDITION; do 循 ...

  7. matplot绘图(五)

    b3D图形绘制 # 导包:from mpl_toolkits.mplot3d.axes3d import Axes3Dimport matplotlib.pyplot as plt%matplotli ...

  8. 如何用纯 CSS 创作一个极品飞车 loader

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/MBbEMo 可交互视频 ...

  9. 剑指Offer(书):不用四则运算做加法

    题目:写一个函数,求两个整数之和,不得使用四则运算位运算. package com.gjjun.jzoffer; /** * 写一个函数,求两个整数之和,不得使用四则运算 * * @author gj ...

  10. Linux学习-分析登录档

    CentOS 预设提供的 logwatch 不过,要了解系统的状态,还是得要分析整个登录档才行~ 事实上, 目前已经有相当多的登录档分析工具,例如 CentOS 7.x 上面预设的 logwatch ...