博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ4817[Sdoi2017]树点涂色
阅读量:5794 次
发布时间:2019-06-18

本文共 3366 字,大约阅读时间需要 11 分钟。

sdoi是真的舒服QAQ

比较神奇的数据结构上树题233

我们观察这个题的性质 发现将一条到1的路径染色很像LCT的access操作 我们不妨将相同颜色的点放在一个splay里面 然后access的时候 一条重边变成轻边的时候其实是 子树内ans +1 可以理解成原来它和它上面的节点颜色原本是相同的 然后断开边表示颜色不同了 轻边变成重边 子树内ans -1 原因同理 于是我们首先需要LCT来维持树的结构

子树内加减->我会dfs序上线段树! 于是我们可以用线段树维护子树内答案 询问3就变成了区间rmq

我们剩下了询问2 询问2怎么做呢? 路径问题! 树上差分!

我们发现这个“权值”也是满足树上差分的性质的 我们可以对其维护它到1号点的ans记为f[i]

于是第二问的答案就是f[x]+f[y]-2*f[lca]+1 (比较神奇 无论lca的颜色是否存在在路径上都是满足这个差分的)

所以我们最后只需要LCT维护树的形态 然后dfs序上线段树维护f 单点查询&区间查询大小值即可QwQ

附代码。(我的代码真的好看233)

#include
#include
#include
#include
#define inf 20021225#define mxn 100010#define lson x<<1#define rson x<<1|1#define fa(x) t[x].fa#define ls(x) t[x].son[0]#define rs(x) t[x].son[1]#define not_root(x) (ls(fa(x))==x||rs(fa(x))==x)#define ll long long#define lg 18using namespace std;struct node{int son[2],fa;bool rev;}t[mxn];struct edge{int to,lt;}e[mxn<<1];int in[mxn],cnt,dep[mxn],dfn[mxn],tot;int ff[mxn],n,sz[mxn],fa[mxn][lg+1],d[mxn];struct Segtree{ int mx[mxn<<2],tag[mxn<<2]; void pushup(int x){mx[x]=max(mx[lson],mx[rson]);} void pushdown(int x) { if(tag[x]) { mx[lson]+=tag[x]; tag[lson]+=tag[x]; mx[rson]+=tag[x]; tag[rson]+=tag[x]; tag[x]=0; } } void build(int x,int l,int r) { if(l==r){mx[x]=ff[d[l]];return;} int mid=(l+r)>>1; build(lson,l,mid);build(rson,mid+1,r); pushup(x); } void modify(int x,int l,int r,int LL,int RR,int v) { if(l>=LL&&r<=RR){mx[x]+=v;tag[x]+=v;return;} int mid=(l+r)>>1;pushdown(x); if(LL<=mid) modify(lson,l,mid,LL,RR,v); if(RR>mid) modify(rson,mid+1,r,LL,RR,v); pushup(x); } int query(int x,int l,int r,int LL,int RR) { if(l>=LL&&r<=RR) return mx[x]; int mid=(l+r)>>1,ans=0;pushdown(x); if(LL<=mid) ans=max(ans,query(lson,l,mid,LL,RR)); if(RR>mid) ans=max(ans,query(rson,mid+1,r,LL,RR)); return ans; } int getans(int x) { return query(1,1,n,dfn[x],dfn[x]); }}T;void add(int x,int y){ e[++cnt].to=y;e[cnt].lt=in[x];in[x]=cnt; e[++cnt].to=x;e[cnt].lt=in[y];in[y]=cnt;}void rotate(int x){ if(!x||!not_root(x)) return; int f=fa(x),gf=fa(f); int k=rs(f)==x,p=k^1; if(not_root(f)) t[gf].son[t[gf].son[1]==f]=x; t[x].fa=gf;t[f].fa=x; t[f].son[k]=t[x].son[p]; if(t[x].son[p]) t[t[x].son[p]].fa=f; t[x].son[p]=f;}void splay(int x){ while(not_root(x)) { int f=fa(x),gf=fa(f); if(not_root(gf)) (rs(f)==x)^(rs(gf)==f)?rotate(x):rotate(f); rotate(x); }}int findroot(int x){ while(ls(x)) x=ls(x); return x;}void access(int x){ int y=0,w; do { splay(x); if(rs(x)) w=findroot(rs(x)),T.modify(1,1,n,dfn[w],dfn[w]+sz[w]-1,1); t[x].son[1]=y; if(rs(x)) w=findroot(rs(x)),T.modify(1,1,n,dfn[w],dfn[w]+sz[w]-1,-1); y=x;x=t[x].fa; }while(x);}void dfs(int x){ ff[x]=dep[x];dfn[x]=++tot;d[tot]=x;sz[x]=1;t[x].fa=fa[x][0]; for(int i=1;i<=lg;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for(int i=in[x];i;i=e[i].lt) { int y=e[i].to; if(dep[y]) continue; dep[y]=dep[x]+1;fa[y][0]=x; dfs(y);sz[x]+=sz[y]; }}int jump(int x,int len){ for(int i=0;i<=lg;i++) if(len&(1<

 

转载于:https://www.cnblogs.com/hanyuweining/p/10321943.html

你可能感兴趣的文章
ORACLE 11G在Linux下的标准安装方法(下)
查看>>
三星的“后手机时代”:电视崛起,构建新生态叫板Android
查看>>
在vSphere网络中不能只在交换机一端配置链路聚合
查看>>
易信对决微信:市场需要挑战者
查看>>
2015年值得关注的几个WEB技术
查看>>
项目组CentOS开发环境的搭建
查看>>
Zen Cart 如何添加地址栏上的小图标
查看>>
2012.11.10项目经理考试核心关注点1_《系统集成项目管理工程师软考辅导——3年真题透解与全真模拟》...
查看>>
又到红包季,QQ红包强势出击欲何为?
查看>>
大学课程能给我们带来什么?——“我们能从大学得到什么”系列之三
查看>>
webdis实现Redis的http接口及多数据格式共享 [含json,restful]
查看>>
网站另类推广玩法心得
查看>>
直播答题APP撒币背后,这些行业可能被革命!
查看>>
objective-c Foundation kit
查看>>
小企鹅输入法 安装 设置 支持中文 for ubuntu 10.04
查看>>
PDB文件概说
查看>>
将 ASP.NET MVC3 Razor 项目部署到虚拟主机中
查看>>
Js~实现public和private对象,即static修饰符
查看>>
C/C++的static成员
查看>>
Microsoft Excel 不能访问文件“ 文件名称或路径不存在。 • 文件正被其他程序使用。 • 您正要保存的工作簿与当前打开的工作簿同名。...
查看>>