[Sdoi2017]树点涂色 [lct 线段树]
[Sdoi2017]树点涂色
题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值
考场发现这个信息是可减的,但是没想到lct
特意设计成lct的形式!
如何求颜色数?
维护一个点和父亲的颜色是否一样,不一样为1,就是前缀和。考虑相邻的思想和那道“水位线”有点像
x到y的答案就是\(S_x + S_y - 2*S_{lca} + 1\)
一个点到根染新颜色,对应了lct的access操作,重边就是一样轻边就是不一样,修改轻重边就是子树加,其他两个操作单点求值,子树求最大值。用线段树维护dfs序
实现上注意:
- access过程中,不能直接修改rc和y,因为splay的形态是不断变化的,应该修改它们所在的splay代表的原树的根
- 并且要先把rc与x重边切断再找根
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
const int N=1e5+5;
#define fir first
#define sec second
inline int read() {
char c=getchar(); int x=0, f=1;
while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
return x*f;
}
int n, Q, op, x, y;
struct edge{int v, ne;} e[N<<1];
int cnt=1, h[N];
inline void ins(int u, int v) {
e[++cnt]=(edge){v, h[u]}; h[u]=cnt;
e[++cnt]=(edge){u, h[v]}; h[v]=cnt;
}
int fa[N], deep[N], size[N], mx[N], top[N], dfc, ver[N];
pair<int, int> dfn[N];
void dfs(int u) {
size[u]=1;
for(int i=h[u];i;i=e[i].ne)
if(e[i].v != fa[u]) {
int v=e[i].v;
fa[v] = u; deep[v] = deep[u]+1;
dfs(v);
size[u] += size[v];
if(size[v] > size[mx[u]]) mx[u] = v;
}
}
void dfs(int u, int anc) {
dfn[u].fir = ++dfc; ver[dfc] = u;
top[u] = anc;
if(mx[u]) dfs(mx[u], anc);
for(int i=h[u];i;i=e[i].ne)
if(e[i].v != fa[u] && e[i].v != mx[u]) dfs(e[i].v, e[i].v);
dfn[u].sec = dfc;
}
inline int lca(int x, int y) {
while(top[x] != top[y]) {
if(deep[top[x]] < deep[top[y]]) swap(x, y);
x = fa[top[x]];
}
return deep[x] < deep[y] ? x : y;
}
namespace seg {
#define mid ((l+r)>>1)
#define lc x<<1
#define rc x<<1|1
#define lson lc, l, mid
#define rson rc, mid+1, r
struct meow{int tag, max;} t[N<<2];
inline void paint(int x, int v) {
t[x].tag += v; t[x].max += v;
}
inline void pushdn(int x) {
if(t[x].tag) {
paint(lc, t[x].tag);
paint(rc, t[x].tag);
t[x].tag = 0;
}
}
inline void merge(int x) {t[x].max = max(t[lc].max, t[rc].max);}
void build(int x, int l, int r) {
if(l == r) t[x].max = deep[ ver[l] ] + 1;
else build(lson), build(rson), merge(x);
}
void add(int x, int l, int r, int ql, int qr, int v) {
if(ql<=l && r<=qr) paint(x, v);
else {
pushdn(x);
if(ql <= mid) add(lson, ql, qr, v);
if(mid < qr ) add(rson, ql, qr, v);
merge(x);
}
}
int que(int x, int l, int r, int p) {
if(l == r) return t[x].max;
else {
pushdn(x);
if(p <= mid) return que(lson, p);
else return que(rson, p);
}
}
int que(int x, int l, int r, int ql, int qr) {
if(ql<=l && r<=qr) return t[x].max;
else {
pushdn(x);
int ans=0;
if(ql <= mid) ans = max(ans, que(lson, ql, qr));
if(mid < qr ) ans = max(ans, que(rson, ql, qr));
return ans;
}
}
#undef lc
#undef rc
}
inline void addsub(int u, int val) {
seg::add(1, 1, n, dfn[u].fir, dfn[u].sec, val);
}
inline void quer(int x, int y) {
int p = lca(x, y);
int ans = seg::que(1, 1, n, dfn[x].fir) + seg::que(1, 1, n, dfn[y].fir) - 2 * seg::que(1, 1, n, dfn[p].fir) + 1;
printf("%d\n", ans);
}
inline void qmax(int x) {
int ans = seg::que(1, 1, n, dfn[x].fir, dfn[x].sec);
printf("%d\n", ans);
}
namespace lct {
#define lc t[x].ch[0]
#define rc t[x].ch[1]
#define pa t[x].fa
struct meow{int ch[2], fa;} t[N];
int sz;
inline int wh(int x) {return t[pa].ch[1] == x;}
inline int isr(int x) {return t[pa].ch[0] != x && t[pa].ch[1] != x;}
inline void rotate(int x) {
int f=t[x].fa, g=t[f].fa, c=wh(x);
if(!isr(f)) t[g].ch[wh(f)] = x; t[x].fa = g;
t[f].ch[c] = t[x].ch[c^1]; t[ t[f].ch[c] ].fa = f;
t[x].ch[c^1] = f; t[f].fa = x;
}
inline void splay(int x) {
for(; !isr(x); rotate(x))
if(!isr(pa)) rotate(wh(x) == wh(pa) ? pa : x);
}
inline int findr(int x) {
splay(x); while(lc) x=lc; splay(x);
return x;
}
void access(int x) {
for(int y=0; x; y=x, x=pa) {
splay(x);
if(rc) {
int u=rc; rc=0;
u=findr(u), addsub(u, 1);
}
if(y) y=findr(y), addsub(y, -1);
rc=y;
}
}
void init() {for(int i=1; i<=n; i++) t[i].fa = fa[i];}
}
int main() {
//freopen("in", "r", stdin);
freopen("paint.in", "r", stdin);
freopen("paint.out", "w", stdout);
n=read(); Q=read();
for(int i=1; i<n; i++) ins(read(), read());
dfs(1); dfs(1, 1); seg::build(1, 1, n); lct::init();
//for(int i=1; i<=n; i++) printf("%d ", ver[i]); puts(" ver");
for(int i=1; i<=Q; i++) {
op=read(); x=read();
if(op==1) lct::access(x);
else if(op==2) y=read(), quer(x, y);
else qmax(x);
}
}
[Sdoi2017]树点涂色 [lct 线段树]的更多相关文章
- 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树
[BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...
- 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]
树点涂色 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1 ...
- [SDOI2017][bzoj4817] 树点涂色 [LCT+线段树]
题面 传送门 思路 $LCT$ 我们发现,这个1操作,好像非常像$LCT$里面的$Access$啊~ 那么我们尝试把$Access$操作魔改成本题中的涂色 我们令$LCT$中的每一个$splay$链代 ...
- BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)
题目大意:略 涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上 用$LCT$维护一个树上集合就好 因为它维护了树上集合,所以它别的啥都干不了了 发现树是静态的 ...
- BZOJ4817[Sdoi2017]树点涂色——LCT+线段树
题目描述 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进 ...
- bzoj4817 & loj2001 [Sdoi2017]树点涂色 LCT + 线段树
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4817 https://loj.ac/problem/2001 题解 可以发现这个题就是 bzo ...
- 【bzoj4817】树点涂色 LCT+线段树+dfs序
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- BZOJ 4817 [Sdoi2017]树点涂色 ——LCT 线段树
同BZOJ3779. SDOI出原题,还是弱化版的. 吃枣药丸 #include <map> #include <cmath> #include <queue> # ...
- BZOJ 4817: [Sdoi2017]树点涂色(lct+线段树)
传送门 解题思路 跟重组病毒这道题很像.只是有了一个询问\(2\)的操作,然后询问\(2\)的答案其实就是\(val[x]+val[y]-2*val[lca(x,y)]+1\)(画图理解).剩下的操作 ...
随机推荐
- oracle ebs form开发总结
item的布局千万不要去乱动,只要调好长宽和y轴的坐标就好了.form内部集成了很多代码对布局进行动态的调整,而且有一些代码的长宽什么的还是写死了的,我们一动,form可能就识别不了了,然后就显示出来 ...
- URL编码的方法
Global 对象的encodeURI()和encodeURIComponent()方法可以对URI(Uniform ResourceIdentifiers,通用资源标识符)进行编码,以便发送给浏览器 ...
- Spark算子--leftOuterJoin和rightOuterJoin
转载请标明出处http://www.cnblogs.com/haozhengfei/p/cb71cd3ac5d7965a2c61891659264d54.html leftOuterJoin和righ ...
- thinkphp使用PHPMailer发送邮件
第一步:准备PHPMailer 使用PHPMailer发送邮件,首先下载个PHPMailer 将下载的PHPMailer放到ThinkPHP文件夹里面的ThinkPHPExtendVendor 第二步 ...
- dedecms_
2012-7-5(no1)当我们点击检索结果的某个电影超链接时,如何跳转到对应的内容页[本资源由www.qinglongweb.com搜集整理] dedelist标签 --可以嵌套 项目移植: mys ...
- 从CUMT校园导航出现的问题看CSS布局设计(一) CSS盒模型
先说说做的这个校园导航系统值得一提的内容: 1. 二级菜单栏 .iframe内嵌窗口(样式设计.用hover做效果) 2. 高德地图API (自定义底图样式.弹跳点.信息窗体.线路导航) 3. DO ...
- CSS用HTML中的style属性替换
废话不多说上代码: 1.用CSS给文字添加背景色: <html> <head> <style type="text/css"> body {ba ...
- ASIHTTPRequest
ASIHTTPRequest,是一个直接在CFNetwork上做的开源项目,提供了一个比官方更方便更强大的HTTP网络传输的封装.
- Android-第二天(2)
程序3 SimpleAdapter是扩展性最好的适配器,可以定义各种你想要的布局,而且使用很方便 SimpleAdapter(Context context, List<? extends Ma ...
- 一天浓缩学习webpack经过
熟话说浓缩就是精华,哈哈,所以就这么简单粗暴的介绍下吧,写下的都是精华. 已经不是第一次听说webpack,但是我的起步有点晚,现在才看.开门见山~~ 1.什么是webpack? webpack是当下 ...