正题

题目链接:https://www.luogu.com.cn/problem/P3703


题目大意

nnn个点的一棵树开始所有点有不同的颜色,mmm次操作

  1. 将根节点到xxx节点的路径上染上一种新的颜色
  2. 询问一条路径的不同颜色个数
  3. 询问一个节点的子树中的一个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(nlog⁡2n)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,线段树】相关推荐

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

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

  2. [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 629  Solved: 371 [Submit][Stat ...

  3. 【线段树】【LCT】【LCA】树点涂色(luogu 3703)

    树点涂色 luogu 3703 题目大意 给出一棵树,每个节点的初始颜色不同,做若干操作: 1.在一个点到根节点路径上染上一种新的颜色 2.查询一条路径上有多少种不同的颜色 3.查询一个点x,使该点到 ...

  4. BZOJ 4817: [Sdoi2017]树点涂色

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 273  Solved: 164 [Submit][Stat ...

  5. P6242-[模板]线段树3【吉司机线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P6242 题目大意 给出一个长度为nnn的序列aaa,mmm次要求支持操作 区间加上一个值kkk 区间所有aia_i ...

  6. 【BZOJ4515】游戏,树链剖分+永久化标记线段树维护线段信息(李超线段树)

    Time:2016.05.10 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 李超线段树 一开始听faebdc讲,并没有听的很懂ww 后来找到良心博文啊有木有 折越 首先可以把修改 ...

  7. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  8. 线段树简单入门 (含普通线段树, zkw线段树, 主席树)

    线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...

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

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

最新文章

  1. 7年,从“游戏少年”到大厂技术总监的逆袭之路
  2. 别把个人信息“玩”丢了
  3. 云网融合 — 云网络的边界
  4. Spring实战之三:高级装配
  5. python下载大文件mp4_Python代码打开本地.mp4格式文件的方法
  6. JavaScript数据结构与算法——队列详解(下)
  7. Qt中如何获得文件和文件夹的路径信息
  8. 写个买卖小游戏,第1天(昨天)
  9. 学计算机之路写一篇作文,写我的学艺之路作文
  10. IS-IS详解(十五)——IS-IS 认证
  11. Maven的核心笔记(3)常用命令、坐标和仓库
  12. C#学习网站资源一览
  13. bing翻译api php,免费翻译接口
  14. 【粗解】【通信编码】卷积编码器的简单实现
  15. 机器视觉硬件之工业相机(一)
  16. java中lookup函数怎么用,excel Lookup查表函数的使用方法
  17. ( )可用来更改计算机系统的设置,2018年职称计算机考试考前冲刺练习及答案(9)...
  18. 史上最“奇葩”相亲男惊呆网友:你那么普通,却那么自信
  19. 附合导线简易平差(4500PA)
  20. android 自动设置时区,Android Things入门-设置本地时区

热门文章

  1. java跨平台的特性_【简答题】什么是跨平台特性?Java怎样实现跨平台特性?
  2. java输入数据插入if_java编程,从键盘录入10个整数数据,将每次录入的数据按从小到大的顺序插入到数组中。...
  3. linux 连接wifi wpa2,RHEL等Linux系统使用wpa_supplicant以WPA-PSK/WPA2-PSK连接WIFI
  4. 未发现android设备,Brother iPrintScan 应用程序上出现错误信息“未发现支持设备”(Android™ 智能手机)。...
  5. 京东笔试4.2-19:00随笔
  6. 7-2 批处理作业调度 (10 分)(思路+详解)
  7. [C++11]独占的智能指针unique_ptr的删除器
  8. 洛谷 P2040 打开所有的灯-dfs
  9. Bridge(桥接)--对象结构模式
  10. GCD and LCM Aizu - 0005(辗转相除)+GCD LCM Inverse POJ - 2429(java或【Miller Rabin素数測试】+【Pollar Rho整数分解】)