P3703-[SDOI2017]树点涂色【LCT,线段树】
正题
题目链接:https://www.luogu.com.cn/problem/P3703
题目大意
nnn个点的一棵树开始所有点有不同的颜色,mmm次操作
- 将根节点到xxx节点的路径上染上一种新的颜色
- 询问一条路径的不同颜色个数
- 询问一个节点的子树中的一个xxx使得xxx到根节点的颜色最多。
解题思路
操作111和LCTLCTLCT的accessaccessaccess操作很相似。相同颜色之间就是实边,不同颜色之间就是虚边。
操作222就是之间px+py−2pLCA+1p_x+p_y-2p_{LCA}+1px+py−2pLCA+1就好了,但是考虑到操作333,所以维护一个dfndfndfn序和线段树就可以查询子树最大值了。
之后维护一个LCTLCTLCT,在accessaccessaccess操作切换虚实边的时候修改一下线段树就好了,并且需要注意我们不能直接拿SplaySplaySplay的根的子树,要找到实际的树中的根,所以SplaySplaySplay一直往左就好了。
好像还有树链剖分的做法,线段树查询的时候维护一下末尾颜色好像就可以了,这里不多讲(我也不会)
时间复杂度O(nlog2n)O(n\log^2 n)O(nlog2n)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
struct node{int to,next;
}a[N<<1];
int n,m,cnt,tot,ls[N],rfn[N],ed[N],fa[N];
int dep[N],son[N],siz[N],top[N];
struct SegTree{int w[N<<2],lazy[N<<2];void Downdata(int x){if(!lazy[x])return;w[x*2]+=lazy[x];lazy[x*2]+=lazy[x];w[x*2+1]+=lazy[x];lazy[x*2+1]+=lazy[x];lazy[x]=0;return;}void Change(int x,int L,int R,int l,int r,int val){if(L==l&&R==r){w[x]+=val;lazy[x]+=val;return;}int mid=(L+R)>>1;Downdata(x);if(r<=mid)Change(x*2,L,mid,l,r,val);else if(l>mid)Change(x*2+1,mid+1,R,l,r,val);else Change(x*2,L,mid,l,mid,val),Change(x*2+1,mid+1,R,mid+1,r,val);w[x]=max(w[x*2],w[x*2+1]);return;}int Ask(int x,int L,int R,int l,int r){if(L==l&&R==r)return w[x];int mid=(L+R)>>1;Downdata(x);if(r<=mid)return Ask(x*2,L,mid,l,r);if(l>mid)return Ask(x*2+1,mid+1,R,l,r);return max(Ask(x*2,L,mid,l,mid),Ask(x*2+1,mid+1,R,mid+1,r));}
}Tr;
struct LinkCutTree{int t[N][2],fa[N];bool Nroot(int x){return fa[x]&&(t[fa[x]][0]==x||t[fa[x]][1]==x);}bool Direct(int x){return t[fa[x]][1]==x;}void Rotate(int x){int y=fa[x],z=fa[y];int xs=Direct(x),ys=Direct(y);int w=t[x][xs^1];if(Nroot(y))t[z][ys]=x;t[x][xs^1]=y;t[y][xs]=w;if(w)fa[w]=y;fa[y]=x;fa[x]=z;return;}void Splay(int x){while(Nroot(x)){int y=fa[x];if(!Nroot(y))Rotate(x);else if(Direct(x)==Direct(y))Rotate(y),Rotate(x);else Rotate(x),Rotate(x);}return;}int FindRoot(int x){while(t[x][0])x=t[x][0];return x;}void Access(int x){for(int y=0;x;y=x,x=fa[x]){Splay(x);int z=t[x][1];if(z)z=FindRoot(z),Tr.Change(1,1,n,rfn[z],ed[z],1);if(y)z=FindRoot(y),Tr.Change(1,1,n,rfn[z],ed[z],-1);t[x][1]=y;}return;}
}T;
void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
void dfs1(int x){siz[x]=1;rfn[x]=++cnt;dep[x]=dep[fa[x]]+1;T.fa[x]=fa[x];Tr.Change(1,1,n,cnt,cnt,dep[x]);for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa[x])continue;fa[y]=x;dfs1(y);siz[x]+=siz[y];if(siz[y]>siz[son[x]])son[x]=y;}ed[x]=cnt;
}
void dfs2(int x){if(son[x]){top[son[x]]=top[x];dfs2(son[x]);}for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa[x]||y==son[x])continue;top[y]=y;dfs2(y);}return;
}
int LCA(int x,int y){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);x=fa[top[x]];}return dep[x]<dep[y]?x:y;
}
int main()
{// freopen("paint1.in","r",stdin);scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}dfs1(1);dfs2(1);while(m--){int op,x,y;scanf("%d%d",&op,&x);if(op==1)T.Access(x);else if(op==2){scanf("%d",&y);int lca=LCA(x,y);int p1=Tr.Ask(1,1,n,rfn[x],rfn[x]);int p2=Tr.Ask(1,1,n,rfn[y],rfn[y]);int p3=Tr.Ask(1,1,n,rfn[lca],rfn[lca]);printf("%d\n",p1+p2-p3*2+1);}else printf("%d\n",Tr.Ask(1,1,n,rfn[x],ed[x]));}return 0;
}
P3703-[SDOI2017]树点涂色【LCT,线段树】相关推荐
- 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]
树点涂色 Time Limit: 10 Sec Memory Limit: 128 MB [Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中 ...
- [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 629 Solved: 371 [Submit][Stat ...
- 【线段树】【LCT】【LCA】树点涂色(luogu 3703)
树点涂色 luogu 3703 题目大意 给出一棵树,每个节点的初始颜色不同,做若干操作: 1.在一个点到根节点路径上染上一种新的颜色 2.查询一条路径上有多少种不同的颜色 3.查询一个点x,使该点到 ...
- BZOJ 4817: [Sdoi2017]树点涂色
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 273 Solved: 164 [Submit][Stat ...
- P6242-[模板]线段树3【吉司机线段树】
正题 题目链接:https://www.luogu.com.cn/problem/P6242 题目大意 给出一个长度为nnn的序列aaa,mmm次要求支持操作 区间加上一个值kkk 区间所有aia_i ...
- 【BZOJ4515】游戏,树链剖分+永久化标记线段树维护线段信息(李超线段树)
Time:2016.05.10 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 李超线段树 一开始听faebdc讲,并没有听的很懂ww 后来找到良心博文啊有木有 折越 首先可以把修改 ...
- BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...
- 线段树简单入门 (含普通线段树, zkw线段树, 主席树)
线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...
- BZOJ 4817: [Sdoi2017]树点涂色(LCT+树剖+线段树)
题目描述 Bob有一棵 nn 个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. Bob ...
最新文章
- 7年,从“游戏少年”到大厂技术总监的逆袭之路
- 别把个人信息“玩”丢了
- 云网融合 — 云网络的边界
- Spring实战之三:高级装配
- python下载大文件mp4_Python代码打开本地.mp4格式文件的方法
- JavaScript数据结构与算法——队列详解(下)
- Qt中如何获得文件和文件夹的路径信息
- 写个买卖小游戏,第1天(昨天)
- 学计算机之路写一篇作文,写我的学艺之路作文
- IS-IS详解(十五)——IS-IS 认证
- Maven的核心笔记(3)常用命令、坐标和仓库
- C#学习网站资源一览
- bing翻译api php,免费翻译接口
- 【粗解】【通信编码】卷积编码器的简单实现
- 机器视觉硬件之工业相机(一)
- java中lookup函数怎么用,excel Lookup查表函数的使用方法
- ( )可用来更改计算机系统的设置,2018年职称计算机考试考前冲刺练习及答案(9)...
- 史上最“奇葩”相亲男惊呆网友:你那么普通,却那么自信
- 附合导线简易平差(4500PA)
- android 自动设置时区,Android Things入门-设置本地时区
热门文章
- java跨平台的特性_【简答题】什么是跨平台特性?Java怎样实现跨平台特性?
- java输入数据插入if_java编程,从键盘录入10个整数数据,将每次录入的数据按从小到大的顺序插入到数组中。...
- linux 连接wifi wpa2,RHEL等Linux系统使用wpa_supplicant以WPA-PSK/WPA2-PSK连接WIFI
- 未发现android设备,Brother iPrintScan 应用程序上出现错误信息“未发现支持设备”(Android™ 智能手机)。...
- 京东笔试4.2-19:00随笔
- 7-2 批处理作业调度 (10 分)(思路+详解)
- [C++11]独占的智能指针unique_ptr的删除器
- 洛谷 P2040 打开所有的灯-dfs
- Bridge(桥接)--对象结构模式
- GCD and LCM Aizu - 0005(辗转相除)+GCD LCM Inverse POJ - 2429(java或【Miller Rabin素数測试】+【Pollar Rho整数分解】)